foobara 0.6.2 → 0.6.3
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/CHANGELOG.md +6 -0
- data/README.md +6 -3
- data/projects/command/lib/foobara/command.rb +2 -0
- data/projects/command/src/command_pattern_implementation/concerns/callbacks.rb +6 -4
- data/projects/command/src/command_pattern_implementation/concerns/command_data.rb +1 -2
- data/projects/command/src/command_pattern_implementation/concerns/runtime.rb +15 -20
- data/projects/command/src/extensions/domain/domain_module_extension_extension.rb +0 -2
- data/projects/command/src/state_machine.rb +3 -15
- data/projects/command_connectors/src/authenticator_selector.rb +0 -8
- data/projects/command_connectors/src/command_connector/request.rb +0 -32
- data/projects/command_connectors/src/command_registry/exposed_command.rb +1 -53
- data/projects/command_connectors/src/serializers/json_serializer.rb +1 -1
- data/projects/entities/projects/detached_entity/src/extensions/type_declarations/handlers/registered_type_declaration/validate_primary_key_present.rb +1 -1
- data/projects/entities/projects/entity/src/new_prepend.rb +2 -4
- data/projects/entities/projects/model_attribute_helpers/lib/foobara/model_attribute_helpers.rb +0 -4
- data/projects/entities/projects/persistence/src/entity_base/transaction_table.rb +1 -2
- data/projects/entities_plumbing/lib/foobara/entities_plumbing.rb +60 -5
- data/projects/entities_plumbing/src/extensions/command_connector/authenticator_selector.rb +13 -0
- data/projects/entities_plumbing/src/extensions/command_connector/request.rb +37 -0
- data/projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/transactional_runtime.rb +29 -0
- data/projects/entities_plumbing/src/extensions/command_registry/exposed_command_entities.rb +71 -0
- data/projects/{command_connectors → entities_plumbing}/src/serializers/entities_to_primary_keys_serializer.rb +0 -2
- data/projects/{command_connectors → entities_plumbing}/src/serializers/record_store_serializer.rb +0 -2
- data/projects/{command_connectors → entities_plumbing}/src/transformers/entity_to_primary_key_inputs_transformer.rb +1 -1
- data/projects/typesystem/projects/builtin_types/src/datetime/casters/hash.rb +2 -1
- data/projects/typesystem/projects/project/src/foobara.rb +2 -2
- data/projects/typesystem/projects/project/src/project.rb +8 -5
- data/projects/typesystem/projects/state_machine/src/callbacks.rb +4 -0
- data/projects/typesystem/projects/state_machine/src/state_machine.rb +0 -2
- data/projects/typesystem/projects/types/src/type.rb +1 -1
- data/version.rb +1 -1
- metadata +15 -11
- /data/projects/{command_connectors → entities_plumbing}/src/serializers/aggregate_serializer.rb +0 -0
- /data/projects/{command_connectors → entities_plumbing}/src/serializers/atomic_serializer.rb +0 -0
- /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_aggregates_pre_commit_transformer.rb +0 -0
- /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_aggregates_transformer.rb +0 -0
- /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_atoms_pre_commit_transformer.rb +0 -0
- /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_atoms_transformer.rb +0 -0
- /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 936be6174137c2740ff9ba0bf5470251901aa9dc61bd841baf4af7dc0041e899
|
|
4
|
+
data.tar.gz: fc49e694263c62adefef802dfa8e469aff130237ec815602cab0aaa92983a132
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bacfb096227c140aace0cd32ed77b1f436872936b07a346a2fac976b83b478a4d9babcb217454874e39c3c944cb664562edf777d863856f8e510bfbccea1105a
|
|
7
|
+
data.tar.gz: 63d4cf117cadd2f5e6d9f5a8e220f28e1f726c5781578097899d9a7cda2f2727036d7354338bef46465452c44d36e4c0ddd878ec9c89a6ec976316240c2a452f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# [0.6.3] - 2026-09-11
|
|
2
|
+
|
|
3
|
+
- Eliminate usage of removed JSON.fast_generate
|
|
4
|
+
- A lot of persistence stuff relocated into entities_plumbing project
|
|
5
|
+
- Allow :datetime to handle fractional seconds
|
|
6
|
+
|
|
1
7
|
# [0.6.2] - 2026-08-24
|
|
2
8
|
|
|
3
9
|
- Eliminate all direct uses of Foobara.manifest in the test suite and deprecate it
|
data/README.md
CHANGED
|
@@ -1385,12 +1385,15 @@ And we can see the error in the command's list of possible errors:
|
|
|
1385
1385
|
```
|
|
1386
1386
|
|
|
1387
1387
|
And of course, as expected, tooling has access to information about this error and the command's possible error through manifest
|
|
1388
|
-
metadata:
|
|
1388
|
+
metadata. Let's take a look at how it surfaces through a generic command connector:
|
|
1389
1389
|
|
|
1390
1390
|
```
|
|
1391
|
-
>
|
|
1391
|
+
> require "foobara/command_connectors"
|
|
1392
|
+
> connector = Foobara::CommandConnector.new
|
|
1393
|
+
> connector.connect(Divide)
|
|
1394
|
+
> connector.foobara_manifest[:command][:Divide][:possible_errors]["data.divisor.divide_by_zero"][:error]
|
|
1392
1395
|
==> "Divide::DivideByZeroError"
|
|
1393
|
-
>
|
|
1396
|
+
> connector.foobara_manifest[:error][:"Divide::DivideByZeroError"][:parent]
|
|
1394
1397
|
==> [:command, "Divide"]
|
|
1395
1398
|
```
|
|
1396
1399
|
|
|
@@ -31,6 +31,12 @@ module Foobara
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def state_machine_callback_registry = state_machine.callback_registry
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class << self
|
|
39
|
+
def install_state_machine_callback_methods
|
|
34
40
|
[self, ClassMethods].each do |target|
|
|
35
41
|
[:before, :after].each do |type|
|
|
36
42
|
target.define_method "#{type}_any_transition" do |&block|
|
|
@@ -84,10 +90,6 @@ module Foobara
|
|
|
84
90
|
end
|
|
85
91
|
end
|
|
86
92
|
end
|
|
87
|
-
|
|
88
|
-
def state_machine_callback_registry
|
|
89
|
-
state_machine.callback_registry
|
|
90
|
-
end
|
|
91
93
|
end
|
|
92
94
|
end
|
|
93
95
|
end
|
|
@@ -21,7 +21,7 @@ module Foobara
|
|
|
21
21
|
@is_query = true
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
# rubocop:disable Naming/MemoizedInstanceVariableName
|
|
24
|
+
# rubocop:disable-next Naming/MemoizedInstanceVariableName
|
|
25
25
|
def query?
|
|
26
26
|
return @is_query if defined?(@is_query)
|
|
27
27
|
|
|
@@ -29,7 +29,6 @@ module Foobara
|
|
|
29
29
|
superclass.query?
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
|
-
# rubocop:enable Naming/MemoizedInstanceVariableName
|
|
33
32
|
end
|
|
34
33
|
end
|
|
35
34
|
end
|
|
@@ -26,24 +26,11 @@ module Foobara
|
|
|
26
26
|
|
|
27
27
|
def run
|
|
28
28
|
Foobara::Namespace.use self.class do
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
invoke_with_callbacks_and_transition_in_transaction([
|
|
32
|
-
:cast_and_validate_inputs,
|
|
33
|
-
:load_records,
|
|
34
|
-
:validate_records,
|
|
35
|
-
:validate,
|
|
36
|
-
:run_execute,
|
|
37
|
-
:commit_transaction
|
|
38
|
-
])
|
|
39
|
-
|
|
40
|
-
invoke_with_callbacks_and_transition(:succeed)
|
|
29
|
+
_run_all_steps
|
|
41
30
|
end
|
|
42
31
|
|
|
43
32
|
@outcome
|
|
44
33
|
rescue Halt
|
|
45
|
-
rollback_transaction
|
|
46
|
-
|
|
47
34
|
return outcome if state_machine.currently_errored?
|
|
48
35
|
|
|
49
36
|
if error_collection.empty?
|
|
@@ -73,6 +60,20 @@ module Foobara
|
|
|
73
60
|
|
|
74
61
|
private
|
|
75
62
|
|
|
63
|
+
def _run_all_steps
|
|
64
|
+
# TODO: start moving tests that depend on entities_plumbing into entities_plumbing
|
|
65
|
+
# so that we can hit this code path naturally by not requiring entities_plumbing
|
|
66
|
+
# in this project
|
|
67
|
+
# simplecov:disable
|
|
68
|
+
invoke_with_callbacks_and_transition([
|
|
69
|
+
:cast_and_validate_inputs,
|
|
70
|
+
:validate,
|
|
71
|
+
:run_execute,
|
|
72
|
+
:succeed
|
|
73
|
+
])
|
|
74
|
+
# simplecov:enable
|
|
75
|
+
end
|
|
76
|
+
|
|
76
77
|
def run_execute
|
|
77
78
|
self.raw_result = execute
|
|
78
79
|
result = process_result_using_result_type(raw_result)
|
|
@@ -90,12 +91,6 @@ module Foobara
|
|
|
90
91
|
# can override if desired, default is a no-op
|
|
91
92
|
end
|
|
92
93
|
|
|
93
|
-
def invoke_with_callbacks_and_transition_in_transaction(transition_or_transitions)
|
|
94
|
-
Persistence::EntityBase.using_transactions(transactions) do
|
|
95
|
-
invoke_with_callbacks_and_transition(transition_or_transitions)
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
94
|
def invoke_with_callbacks_and_transition(transition_or_transitions)
|
|
100
95
|
result = nil
|
|
101
96
|
|
|
@@ -2,13 +2,9 @@ module Foobara
|
|
|
2
2
|
class Command
|
|
3
3
|
class StateMachine < Foobara::StateMachine
|
|
4
4
|
transitions = [
|
|
5
|
-
:open_transaction,
|
|
6
5
|
:cast_and_validate_inputs,
|
|
7
|
-
:load_records,
|
|
8
|
-
:validate_records,
|
|
9
6
|
:validate,
|
|
10
7
|
:run_execute,
|
|
11
|
-
:commit_transaction,
|
|
12
8
|
:succeed,
|
|
13
9
|
:error,
|
|
14
10
|
:fail,
|
|
@@ -19,26 +15,18 @@ module Foobara
|
|
|
19
15
|
|
|
20
16
|
states = [
|
|
21
17
|
:initialized,
|
|
22
|
-
:transaction_opened,
|
|
23
18
|
:inputs_casted_and_validated,
|
|
24
|
-
:loaded_records,
|
|
25
|
-
:validated_records,
|
|
26
19
|
:validated_execution,
|
|
27
20
|
:executing,
|
|
28
|
-
:transaction_committed
|
|
29
21
|
] + terminal_states
|
|
30
22
|
|
|
31
23
|
can_fail_states = states - terminal_states
|
|
32
24
|
|
|
33
25
|
transition_map = {
|
|
34
|
-
initialized: {
|
|
35
|
-
|
|
36
|
-
inputs_casted_and_validated: { load_records: :loaded_records },
|
|
37
|
-
loaded_records: { validate_records: :validated_records },
|
|
38
|
-
validated_records: { validate: :validated_execution },
|
|
26
|
+
initialized: { cast_and_validate_inputs: :inputs_casted_and_validated },
|
|
27
|
+
inputs_casted_and_validated: { validate: :validated_execution },
|
|
39
28
|
validated_execution: { run_execute: :executing },
|
|
40
|
-
executing: {
|
|
41
|
-
transaction_committed: { succeed: :succeeded },
|
|
29
|
+
executing: { succeed: :succeeded },
|
|
42
30
|
terminal_states => { reset: :initialized },
|
|
43
31
|
can_fail_states => {
|
|
44
32
|
error: :errored,
|
|
@@ -24,14 +24,6 @@ module Foobara
|
|
|
24
24
|
def authenticate(request)
|
|
25
25
|
selector.process_value!(request)
|
|
26
26
|
end
|
|
27
|
-
|
|
28
|
-
def relevant_entity_classes(request)
|
|
29
|
-
outcome = selector.processor_for(request)
|
|
30
|
-
|
|
31
|
-
if outcome.success?
|
|
32
|
-
outcome.result&.relevant_entity_classes(request)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
27
|
end
|
|
36
28
|
end
|
|
37
29
|
end
|
|
@@ -2,7 +2,6 @@ module Foobara
|
|
|
2
2
|
class CommandConnector
|
|
3
3
|
class Request
|
|
4
4
|
include TruncatedInspect
|
|
5
|
-
include NestedTransactionable
|
|
6
5
|
|
|
7
6
|
# TODO: this feels like a smell of some sort...
|
|
8
7
|
attr_accessor :command,
|
|
@@ -163,39 +162,8 @@ module Foobara
|
|
|
163
162
|
outcome.error_collection
|
|
164
163
|
end
|
|
165
164
|
|
|
166
|
-
# TODO: move this to entity_plumbing
|
|
167
|
-
def relevant_entity_classes
|
|
168
|
-
if command_class.is_a?(::Class) && command_class < TransformedCommand
|
|
169
|
-
if authenticator.respond_to?(:relevant_entity_classes)
|
|
170
|
-
entity_classes = authenticator.relevant_entity_classes(self)
|
|
171
|
-
[*entity_classes, *relevant_entity_classes_from_inputs_transformer]
|
|
172
|
-
else
|
|
173
|
-
relevant_entity_classes_from_inputs_transformer
|
|
174
|
-
end
|
|
175
|
-
end || EMPTY_ARRAY
|
|
176
|
-
end
|
|
177
|
-
|
|
178
165
|
private
|
|
179
166
|
|
|
180
|
-
def relevant_entity_classes_from_inputs_transformer(
|
|
181
|
-
object = [*command_class.inputs_transformer, *command_class.result_transformer]
|
|
182
|
-
)
|
|
183
|
-
case object
|
|
184
|
-
when TypeDeclarations::TypedTransformer
|
|
185
|
-
relevant_entity_classes_from_inputs_transformer([*object.from_type, *object.to_type])
|
|
186
|
-
when Types::Type
|
|
187
|
-
relevant_entity_classes_for_type(object)
|
|
188
|
-
when ::Array
|
|
189
|
-
object.map do |o|
|
|
190
|
-
relevant_entity_classes_from_inputs_transformer(o)
|
|
191
|
-
end.flatten
|
|
192
|
-
when Value::Processor::Pipeline
|
|
193
|
-
relevant_entity_classes_from_inputs_transformer(object.processors)
|
|
194
|
-
else
|
|
195
|
-
[]
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
167
|
def objects_to_serializers(objects)
|
|
200
168
|
objects.map do |object|
|
|
201
169
|
case object
|
|
@@ -35,9 +35,7 @@ module Foobara
|
|
|
35
35
|
allowed_rule: nil,
|
|
36
36
|
requires_authentication: nil,
|
|
37
37
|
authentication_optional: nil,
|
|
38
|
-
authenticator: nil
|
|
39
|
-
aggregate_entities: nil,
|
|
40
|
-
atomic_entities: nil
|
|
38
|
+
authenticator: nil
|
|
41
39
|
)
|
|
42
40
|
if allowed_rule && authenticator && requires_authentication.nil?
|
|
43
41
|
requires_authentication = true
|
|
@@ -57,42 +55,6 @@ module Foobara
|
|
|
57
55
|
command_class.scoped_path
|
|
58
56
|
end
|
|
59
57
|
|
|
60
|
-
if aggregate_entities
|
|
61
|
-
pre_commit_transformers = [
|
|
62
|
-
*pre_commit_transformers,
|
|
63
|
-
CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
|
|
64
|
-
]
|
|
65
|
-
|
|
66
|
-
pre_commit_transformers.uniq!
|
|
67
|
-
pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAtomsPreCommitTransformer)
|
|
68
|
-
|
|
69
|
-
serializers = [*serializers, CommandConnectors::Serializers::AggregateSerializer]
|
|
70
|
-
|
|
71
|
-
serializers.uniq!
|
|
72
|
-
serializers.delete(Foobara::CommandConnectors::Serializers::AtomicSerializer)
|
|
73
|
-
# TODO: either both should have special behavior for false or neither should
|
|
74
|
-
elsif aggregate_entities == false
|
|
75
|
-
pre_commit_transformers = pre_commit_transformers&.reject do |t|
|
|
76
|
-
t == Foobara::CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
|
|
77
|
-
end
|
|
78
|
-
serializers = serializers&.reject do |s|
|
|
79
|
-
s == Foobara::CommandConnectors::Serializers::AggregateSerializer
|
|
80
|
-
end
|
|
81
|
-
elsif atomic_entities
|
|
82
|
-
pre_commit_transformers = [
|
|
83
|
-
*pre_commit_transformers,
|
|
84
|
-
CommandConnectors::Transformers::LoadAtomsPreCommitTransformer
|
|
85
|
-
]
|
|
86
|
-
|
|
87
|
-
pre_commit_transformers.uniq!
|
|
88
|
-
pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer)
|
|
89
|
-
|
|
90
|
-
serializers = [*serializers, Foobara::CommandConnectors::Serializers::AtomicSerializer]
|
|
91
|
-
|
|
92
|
-
serializers.uniq!
|
|
93
|
-
serializers.delete(CommandConnectors::Serializers::AggregateSerializer)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
58
|
self.command_class = command_class
|
|
97
59
|
self.scoped_path = scoped_path
|
|
98
60
|
self.capture_unknown_error = capture_unknown_error
|
|
@@ -108,20 +70,6 @@ module Foobara
|
|
|
108
70
|
self.authentication_optional = authentication_optional
|
|
109
71
|
self.authenticator = authenticator
|
|
110
72
|
|
|
111
|
-
# A bit hacky... we should check if we need to shim in a LoadDelegatedAttributesEntitiesPreCommitTransformer
|
|
112
|
-
unless aggregate_entities
|
|
113
|
-
# It's possible delegates have been added or removed via the result transformers...
|
|
114
|
-
# We should figure out a way to check the transformed result type instead.
|
|
115
|
-
if _has_delegated_attributes?(command_class.result_type)
|
|
116
|
-
self.pre_commit_transformers = [
|
|
117
|
-
*self.pre_commit_transformers,
|
|
118
|
-
CommandConnectors::Transformers::LoadDelegatedAttributesEntitiesPreCommitTransformer
|
|
119
|
-
]
|
|
120
|
-
|
|
121
|
-
pre_commit_transformers.uniq!
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
|
|
125
73
|
Namespace.on_change(self, :clear_caches)
|
|
126
74
|
end
|
|
127
75
|
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
module Foobara
|
|
2
2
|
class Entity < DetachedEntity
|
|
3
3
|
module NewPrepend
|
|
4
|
-
# rubocop:disable Lint/UselessMethodDefinition
|
|
4
|
+
# rubocop:disable-next Lint/UselessMethodDefinition
|
|
5
5
|
def new(...)
|
|
6
6
|
super
|
|
7
7
|
end
|
|
8
|
-
# rubocop:enable Lint/UselessMethodDefinition
|
|
9
8
|
|
|
10
9
|
alias __private_new__ new
|
|
11
10
|
|
|
12
|
-
# rubocop:disable Lint/DuplicateMethods
|
|
11
|
+
# rubocop:disable-next Lint/DuplicateMethods
|
|
13
12
|
def new(...)
|
|
14
13
|
# simplecov:disable
|
|
15
14
|
raise "Cannot initialize a #{name}. Use .create, .thunk, .loaded, or .build instead."
|
|
16
15
|
# simplecov:enable
|
|
17
16
|
end
|
|
18
|
-
# rubocop:enable Lint/DuplicateMethods
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
19
|
end
|
|
@@ -86,7 +86,7 @@ module Foobara
|
|
|
86
86
|
# simplecov:enable
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
# rubocop:disable Lint/IdentityComparison
|
|
89
|
+
# rubocop:disable-next Lint/IdentityComparison
|
|
90
90
|
if entity &&
|
|
91
91
|
(!entity.equal?(entity_or_record_id) || entity.object_id != entity_or_record_id.object_id)
|
|
92
92
|
# simplecov:disable
|
|
@@ -94,7 +94,6 @@ module Foobara
|
|
|
94
94
|
"Try passing in the primary key instead of constructing an unloaded entity to pass in."
|
|
95
95
|
# simplecov:enable
|
|
96
96
|
end
|
|
97
|
-
# rubocop:enable Lint/IdentityComparison
|
|
98
97
|
|
|
99
98
|
record_id = entity.primary_key
|
|
100
99
|
else
|
|
@@ -7,29 +7,84 @@ module Foobara
|
|
|
7
7
|
CommandPatternImplementation.include CommandPatternImplementation::Concerns::EntityInputs
|
|
8
8
|
CommandPatternImplementation.include CommandPatternImplementation::Concerns::EntityErrorsType
|
|
9
9
|
CommandPatternImplementation.include CommandPatternImplementation::Concerns::EntityReflection
|
|
10
|
+
CommandPatternImplementation.include CommandPatternImplementation::Concerns::TransactionalRuntime
|
|
10
11
|
|
|
11
12
|
if Foobara.project_installed?("command_connectors")
|
|
12
13
|
# simplecov:disable
|
|
13
|
-
|
|
14
|
+
install_command_connector_extensions
|
|
14
15
|
# simplecov:enable
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def new_project_added(new_project)
|
|
19
20
|
if new_project.symbol == "command_connectors"
|
|
20
|
-
|
|
21
|
+
install_command_connector_extensions
|
|
21
22
|
end
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
def
|
|
25
|
+
def add_persistence_states_and_transitions
|
|
26
|
+
original_terminal_states = Command::StateMachine.terminal_states
|
|
27
|
+
original_transition_map = Command::StateMachine.transition_map
|
|
28
|
+
|
|
29
|
+
new_transition_map = {}
|
|
30
|
+
|
|
31
|
+
new_transition_map[:initialized] = { open_transaction: :transaction_opened }
|
|
32
|
+
new_transition_map[:transaction_opened] = { cast_and_validate_inputs: :inputs_casted_and_validated }
|
|
33
|
+
new_transition_map[:inputs_casted_and_validated] = { load_records: :loaded_records }
|
|
34
|
+
new_transition_map[:loaded_records] = { validate_records: :validated_records }
|
|
35
|
+
new_transition_map[:validated_records] = { validate: :validated_execution }
|
|
36
|
+
new_transition_map[:validated_execution] = {
|
|
37
|
+
run_execute: original_transition_map[:validated_execution][:run_execute]
|
|
38
|
+
}
|
|
39
|
+
new_transition_map[:executing] = { commit_transaction: :transaction_committed }
|
|
40
|
+
new_transition_map[:transaction_committed] = { succeed: :succeeded }
|
|
41
|
+
|
|
42
|
+
new_transition_map[new_transition_map.keys] = {
|
|
43
|
+
error: :errored,
|
|
44
|
+
fail: :failed
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[:succeeded, :errored, :failed].each do |state|
|
|
48
|
+
new_transition_map[state] = original_transition_map[state]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
Command::StateMachine.remove_all_callbacks
|
|
52
|
+
Command::StateMachine.allow_recreating_callback_methods
|
|
53
|
+
|
|
54
|
+
Command::StateMachine.set_transition_map(
|
|
55
|
+
new_transition_map,
|
|
56
|
+
terminal_states: original_terminal_states
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def install_command_connector_extensions
|
|
25
61
|
CommandConnector.singleton_class.prepend(
|
|
26
62
|
Foobara::EntitiesPlumbing::CommandConnectorsExtension::ClassMethods
|
|
27
63
|
)
|
|
28
64
|
|
|
29
65
|
CommandConnector::Authenticator.include CommandConnector::AuthenticatorMethods
|
|
66
|
+
CommandConnector::Request.include NestedTransactionable
|
|
67
|
+
CommandRegistry::ExposedCommand.prepend CommandRegistry::ExposedCommandEntities
|
|
68
|
+
|
|
69
|
+
project_path = "#{__dir__}/../.."
|
|
70
|
+
|
|
71
|
+
Util.require_directory("#{project_path}/src/extensions/command_connector")
|
|
72
|
+
Util.require_directory("#{project_path}/src/serializers")
|
|
73
|
+
Util.require_directory("#{project_path}/src/transformers")
|
|
30
74
|
end
|
|
31
75
|
end
|
|
76
|
+
|
|
77
|
+
add_persistence_states_and_transitions
|
|
32
78
|
end
|
|
33
|
-
end
|
|
34
79
|
|
|
35
|
-
|
|
80
|
+
project_path = "#{__dir__}/../.."
|
|
81
|
+
|
|
82
|
+
Foobara.project("entities_plumbing",
|
|
83
|
+
project_path:,
|
|
84
|
+
eager_load_src: false)
|
|
85
|
+
|
|
86
|
+
Util.require_directory("#{project_path}/src/extensions/command_pattern_implementation")
|
|
87
|
+
Util.require_directory("#{project_path}/src/extensions/command_registry")
|
|
88
|
+
Util.require_pattern("#{project_path}/src/extensions/authenticator_methods.rb")
|
|
89
|
+
Util.require_pattern("#{project_path}/src/command_connectors_extension.rb")
|
|
90
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
class CommandConnector
|
|
3
|
+
class AuthenticatorSelector < Authenticator
|
|
4
|
+
def relevant_entity_classes(request)
|
|
5
|
+
outcome = selector.processor_for(request)
|
|
6
|
+
|
|
7
|
+
if outcome.success?
|
|
8
|
+
outcome.result&.relevant_entity_classes(request)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
class CommandConnector
|
|
3
|
+
class Request
|
|
4
|
+
def relevant_entity_classes
|
|
5
|
+
if command_class.is_a?(::Class) && command_class < TransformedCommand
|
|
6
|
+
if authenticator.respond_to?(:relevant_entity_classes)
|
|
7
|
+
entity_classes = authenticator.relevant_entity_classes(self)
|
|
8
|
+
[*entity_classes, *relevant_entity_classes_from_inputs_transformer]
|
|
9
|
+
else
|
|
10
|
+
relevant_entity_classes_from_inputs_transformer
|
|
11
|
+
end
|
|
12
|
+
end || EMPTY_ARRAY
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def relevant_entity_classes_from_inputs_transformer(
|
|
18
|
+
object = [*command_class.inputs_transformer, *command_class.result_transformer]
|
|
19
|
+
)
|
|
20
|
+
case object
|
|
21
|
+
when TypeDeclarations::TypedTransformer
|
|
22
|
+
relevant_entity_classes_from_inputs_transformer([*object.from_type, *object.to_type])
|
|
23
|
+
when Types::Type
|
|
24
|
+
relevant_entity_classes_for_type(object)
|
|
25
|
+
when ::Array
|
|
26
|
+
object.map do |o|
|
|
27
|
+
relevant_entity_classes_from_inputs_transformer(o)
|
|
28
|
+
end.flatten
|
|
29
|
+
when Value::Processor::Pipeline
|
|
30
|
+
relevant_entity_classes_from_inputs_transformer(object.processors)
|
|
31
|
+
else
|
|
32
|
+
[]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
module CommandPatternImplementation
|
|
3
|
+
module Concerns
|
|
4
|
+
module TransactionalRuntime
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def _run_all_steps
|
|
8
|
+
invoke_with_callbacks_and_transition(:open_transaction)
|
|
9
|
+
|
|
10
|
+
Persistence::EntityBase.using_transactions(transactions) do
|
|
11
|
+
invoke_with_callbacks_and_transition([
|
|
12
|
+
:cast_and_validate_inputs,
|
|
13
|
+
:load_records,
|
|
14
|
+
:validate_records,
|
|
15
|
+
:validate,
|
|
16
|
+
:run_execute,
|
|
17
|
+
:commit_transaction
|
|
18
|
+
])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
invoke_with_callbacks_and_transition(:succeed)
|
|
22
|
+
rescue
|
|
23
|
+
rollback_transaction
|
|
24
|
+
raise
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Foobara
|
|
2
|
+
class CommandRegistry
|
|
3
|
+
module ExposedCommandEntities
|
|
4
|
+
def initialize(
|
|
5
|
+
command_class,
|
|
6
|
+
pre_commit_transformers: nil,
|
|
7
|
+
serializers: nil,
|
|
8
|
+
aggregate_entities: nil,
|
|
9
|
+
atomic_entities: nil,
|
|
10
|
+
**
|
|
11
|
+
)
|
|
12
|
+
if aggregate_entities
|
|
13
|
+
pre_commit_transformers = [
|
|
14
|
+
*pre_commit_transformers,
|
|
15
|
+
CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
pre_commit_transformers.uniq!
|
|
19
|
+
pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAtomsPreCommitTransformer)
|
|
20
|
+
|
|
21
|
+
serializers = [*serializers, CommandConnectors::Serializers::AggregateSerializer]
|
|
22
|
+
|
|
23
|
+
serializers.uniq!
|
|
24
|
+
serializers.delete(Foobara::CommandConnectors::Serializers::AtomicSerializer)
|
|
25
|
+
# TODO: either both should have special behavior for false or neither should
|
|
26
|
+
elsif aggregate_entities == false
|
|
27
|
+
pre_commit_transformers = pre_commit_transformers&.reject do |t|
|
|
28
|
+
t == Foobara::CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
|
|
29
|
+
end
|
|
30
|
+
serializers = serializers&.reject do |s|
|
|
31
|
+
s == Foobara::CommandConnectors::Serializers::AggregateSerializer
|
|
32
|
+
end
|
|
33
|
+
elsif atomic_entities
|
|
34
|
+
pre_commit_transformers = [
|
|
35
|
+
*pre_commit_transformers,
|
|
36
|
+
CommandConnectors::Transformers::LoadAtomsPreCommitTransformer
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
pre_commit_transformers.uniq!
|
|
40
|
+
pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer)
|
|
41
|
+
|
|
42
|
+
serializers = [*serializers, Foobara::CommandConnectors::Serializers::AtomicSerializer]
|
|
43
|
+
|
|
44
|
+
serializers.uniq!
|
|
45
|
+
serializers.delete(CommandConnectors::Serializers::AggregateSerializer)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# A bit hacky... we should check if we need to shim in a LoadDelegatedAttributesEntitiesPreCommitTransformer
|
|
49
|
+
unless aggregate_entities
|
|
50
|
+
# It's possible delegates have been added or removed via the result transformers...
|
|
51
|
+
# We should figure out a way to check the transformed result type instead.
|
|
52
|
+
if _has_delegated_attributes?(command_class.result_type)
|
|
53
|
+
pre_commit_transformers = [
|
|
54
|
+
*pre_commit_transformers,
|
|
55
|
+
CommandConnectors::Transformers::LoadDelegatedAttributesEntitiesPreCommitTransformer
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
pre_commit_transformers.uniq!
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
super(
|
|
63
|
+
command_class,
|
|
64
|
+
pre_commit_transformers:,
|
|
65
|
+
serializers:,
|
|
66
|
+
**
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -49,7 +49,7 @@ module Foobara
|
|
|
49
49
|
declaration = to_type.target_class.primary_key_type.reference_or_declaration_data
|
|
50
50
|
|
|
51
51
|
if declaration.is_a?(::Symbol)
|
|
52
|
-
declaration = { type: declaration
|
|
52
|
+
declaration = { type: declaration }
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
description = "#{to_type.target_class.model_name} #{to_type.target_class.primary_key_attribute}"
|
|
@@ -43,7 +43,8 @@ module Foobara
|
|
|
43
43
|
day: { type: :integer, min: 1, max: 31 },
|
|
44
44
|
hours: { type: :integer, min: 0, max: 23, required: false, default: 0 },
|
|
45
45
|
minutes: { type: :integer, min: 0, max: 59, required: false, default: 0 },
|
|
46
|
-
|
|
46
|
+
# TODO: add a :rational foobara type
|
|
47
|
+
seconds: { type: :duck, required: false, default: 0 },
|
|
47
48
|
milliseconds: { type: :integer, min: 0, max: 1000, required: false },
|
|
48
49
|
zone: { type: :string, required: false }
|
|
49
50
|
)
|
|
@@ -18,14 +18,14 @@ module Foobara
|
|
|
18
18
|
@all_projects ||= {}
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def project(symbol, project_path: nil)
|
|
21
|
+
def project(symbol, project_path: nil, eager_load_src: true)
|
|
22
22
|
if all_projects.key?(symbol)
|
|
23
23
|
# simplecov:disable
|
|
24
24
|
raise ArgumentError, "Project #{symbol} already loaded"
|
|
25
25
|
# simplecov:enable
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
project = Project.new(symbol, project_path:)
|
|
28
|
+
project = Project.new(symbol, project_path:, eager_load_src:)
|
|
29
29
|
project.load
|
|
30
30
|
|
|
31
31
|
all_projects[symbol] = project
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
module Foobara
|
|
2
2
|
class Project
|
|
3
|
-
attr_accessor :symbol, :project_path
|
|
3
|
+
attr_accessor :symbol, :project_path, :eager_load_src
|
|
4
4
|
|
|
5
|
-
def initialize(symbol, project_path: nil)
|
|
5
|
+
def initialize(symbol, project_path: nil, eager_load_src: true)
|
|
6
|
+
self.eager_load_src = eager_load_src
|
|
6
7
|
self.symbol = symbol
|
|
7
8
|
self.project_path = project_path || "#{__dir__}/../../#{symbol}"
|
|
8
9
|
end
|
|
@@ -22,10 +23,12 @@ module Foobara
|
|
|
22
23
|
def load
|
|
23
24
|
require require_path
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
if eager_load_src
|
|
27
|
+
src_dir = "#{project_path}/src"
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if Dir.exist?(src_dir)
|
|
30
|
+
Util.require_directory(src_dir)
|
|
31
|
+
end
|
|
29
32
|
end
|
|
30
33
|
end
|
|
31
34
|
|
|
@@ -448,7 +448,7 @@ module Foobara
|
|
|
448
448
|
if data.key?(:defaults)
|
|
449
449
|
defaults = data[:defaults]
|
|
450
450
|
|
|
451
|
-
if defaults.is_a?(::Hash) && defaults.values.any?
|
|
451
|
+
if defaults.is_a?(::Hash) && defaults.values.any?(Proc)
|
|
452
452
|
cleaned_defaults = defaults.transform_values do |value|
|
|
453
453
|
if value.is_a?(Proc)
|
|
454
454
|
"[<Lazily Set>]"
|
data/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foobara
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miles Georgi
|
|
@@ -143,23 +143,13 @@ files:
|
|
|
143
143
|
- projects/command_connectors/src/request_mutator.rb
|
|
144
144
|
- projects/command_connectors/src/response_mutator.rb
|
|
145
145
|
- projects/command_connectors/src/serializer.rb
|
|
146
|
-
- projects/command_connectors/src/serializers/aggregate_serializer.rb
|
|
147
|
-
- projects/command_connectors/src/serializers/atomic_serializer.rb
|
|
148
|
-
- projects/command_connectors/src/serializers/entities_to_primary_keys_serializer.rb
|
|
149
146
|
- projects/command_connectors/src/serializers/errors_serializer.rb
|
|
150
147
|
- projects/command_connectors/src/serializers/json_serializer.rb
|
|
151
148
|
- projects/command_connectors/src/serializers/noop_serializer.rb
|
|
152
|
-
- projects/command_connectors/src/serializers/record_store_serializer.rb
|
|
153
149
|
- projects/command_connectors/src/serializers/success_serializer.rb
|
|
154
150
|
- projects/command_connectors/src/serializers/yaml_serializer.rb
|
|
155
151
|
- projects/command_connectors/src/transformed_command.rb
|
|
156
152
|
- projects/command_connectors/src/transformers/auth_errors_transformer.rb
|
|
157
|
-
- projects/command_connectors/src/transformers/entity_to_primary_key_inputs_transformer.rb
|
|
158
|
-
- projects/command_connectors/src/transformers/load_aggregates_pre_commit_transformer.rb
|
|
159
|
-
- projects/command_connectors/src/transformers/load_aggregates_transformer.rb
|
|
160
|
-
- projects/command_connectors/src/transformers/load_atoms_pre_commit_transformer.rb
|
|
161
|
-
- projects/command_connectors/src/transformers/load_atoms_transformer.rb
|
|
162
|
-
- projects/command_connectors/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb
|
|
163
153
|
- projects/domain_mapper/lib/foobara/domain_mapper.rb
|
|
164
154
|
- projects/domain_mapper/src/domain_mapper.rb
|
|
165
155
|
- projects/domain_mapper/src/domain_mapper_lookups.rb
|
|
@@ -250,12 +240,26 @@ files:
|
|
|
250
240
|
- projects/entities_plumbing/lib/foobara/entities_plumbing.rb
|
|
251
241
|
- projects/entities_plumbing/src/command_connectors_extension.rb
|
|
252
242
|
- projects/entities_plumbing/src/extensions/authenticator_methods.rb
|
|
243
|
+
- projects/entities_plumbing/src/extensions/command_connector/authenticator_selector.rb
|
|
244
|
+
- projects/entities_plumbing/src/extensions/command_connector/request.rb
|
|
253
245
|
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entities.rb
|
|
254
246
|
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entity_errors_type.rb
|
|
255
247
|
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entity_inputs.rb
|
|
256
248
|
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entity_reflection.rb
|
|
257
249
|
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/runtime.rb
|
|
250
|
+
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/transactional_runtime.rb
|
|
258
251
|
- projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/transactions.rb
|
|
252
|
+
- projects/entities_plumbing/src/extensions/command_registry/exposed_command_entities.rb
|
|
253
|
+
- projects/entities_plumbing/src/serializers/aggregate_serializer.rb
|
|
254
|
+
- projects/entities_plumbing/src/serializers/atomic_serializer.rb
|
|
255
|
+
- projects/entities_plumbing/src/serializers/entities_to_primary_keys_serializer.rb
|
|
256
|
+
- projects/entities_plumbing/src/serializers/record_store_serializer.rb
|
|
257
|
+
- projects/entities_plumbing/src/transformers/entity_to_primary_key_inputs_transformer.rb
|
|
258
|
+
- projects/entities_plumbing/src/transformers/load_aggregates_pre_commit_transformer.rb
|
|
259
|
+
- projects/entities_plumbing/src/transformers/load_aggregates_transformer.rb
|
|
260
|
+
- projects/entities_plumbing/src/transformers/load_atoms_pre_commit_transformer.rb
|
|
261
|
+
- projects/entities_plumbing/src/transformers/load_atoms_transformer.rb
|
|
262
|
+
- projects/entities_plumbing/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb
|
|
259
263
|
- projects/manifest/lib/foobara/manifest.rb
|
|
260
264
|
- projects/manifest/src/array.rb
|
|
261
265
|
- projects/manifest/src/attributes.rb
|
/data/projects/{command_connectors → entities_plumbing}/src/serializers/aggregate_serializer.rb
RENAMED
|
File without changes
|
/data/projects/{command_connectors → entities_plumbing}/src/serializers/atomic_serializer.rb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/data/projects/{command_connectors → entities_plumbing}/src/transformers/load_atoms_transformer.rb
RENAMED
|
File without changes
|