bcdd-result 0.13.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/CHANGELOG.md +46 -17
  4. data/README.md +381 -220
  5. data/Rakefile +1 -1
  6. data/Steepfile +1 -1
  7. data/examples/multiple_listeners/Rakefile +8 -8
  8. data/examples/multiple_listeners/app/models/account/owner_creation.rb +1 -1
  9. data/examples/multiple_listeners/app/models/user/creation.rb +1 -1
  10. data/examples/multiple_listeners/app/models/user/token/creation.rb +1 -1
  11. data/examples/multiple_listeners/config/initializers/bcdd.rb +0 -2
  12. data/examples/multiple_listeners/config.rb +3 -3
  13. data/examples/multiple_listeners/db/setup.rb +2 -3
  14. data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
  15. data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
  16. data/examples/multiple_listeners/lib/runtime_breaker.rb +1 -1
  17. data/examples/service_objects/Rakefile +36 -0
  18. data/examples/service_objects/app/models/account/member.rb +10 -0
  19. data/examples/service_objects/app/models/account.rb +11 -0
  20. data/examples/service_objects/app/models/user/token.rb +7 -0
  21. data/examples/service_objects/app/models/user.rb +15 -0
  22. data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
  23. data/examples/service_objects/app/services/application_service.rb +79 -0
  24. data/examples/service_objects/app/services/user/creation.rb +56 -0
  25. data/examples/service_objects/app/services/user/token/creation.rb +37 -0
  26. data/examples/service_objects/config/boot.rb +17 -0
  27. data/examples/service_objects/config/initializers/bcdd.rb +9 -0
  28. data/examples/service_objects/config.rb +20 -0
  29. data/examples/service_objects/db/setup.rb +49 -0
  30. data/examples/single_listener/Rakefile +5 -5
  31. data/examples/single_listener/app/models/account/owner_creation.rb +1 -1
  32. data/examples/single_listener/app/models/user/creation.rb +1 -1
  33. data/examples/single_listener/app/models/user/token/creation.rb +1 -1
  34. data/examples/single_listener/config/initializers/bcdd.rb +0 -2
  35. data/examples/single_listener/config.rb +1 -1
  36. data/examples/single_listener/lib/{single_transitions_listener.rb → single_event_logs_listener.rb} +32 -23
  37. data/lib/bcdd/{result/context → context}/callable_and_then.rb +5 -4
  38. data/lib/bcdd/{result/context → context}/expectations/mixin.rb +1 -1
  39. data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
  40. data/lib/bcdd/context/failure.rb +9 -0
  41. data/lib/bcdd/{result/context → context}/mixin.rb +2 -2
  42. data/lib/bcdd/{result/context → context}/success.rb +6 -6
  43. data/lib/bcdd/context.rb +91 -0
  44. data/lib/bcdd/failure.rb +23 -0
  45. data/lib/bcdd/result/_self.rb +198 -0
  46. data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
  47. data/lib/bcdd/result/config/switchers/addons.rb +2 -2
  48. data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
  49. data/lib/bcdd/result/config/switchers/features.rb +5 -5
  50. data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
  51. data/lib/bcdd/result/config.rb +7 -5
  52. data/lib/bcdd/result/contract/type_checker.rb +4 -0
  53. data/lib/bcdd/result/{transitions → event_logs}/config.rb +5 -3
  54. data/lib/bcdd/result/{transitions → event_logs}/listener.rb +5 -5
  55. data/lib/bcdd/result/{transitions → event_logs}/listeners.rb +17 -17
  56. data/lib/bcdd/result/{transitions → event_logs}/tracking/disabled.rb +1 -1
  57. data/lib/bcdd/result/{transitions → event_logs}/tracking/enabled.rb +15 -13
  58. data/lib/bcdd/result/{transitions → event_logs}/tracking.rb +4 -3
  59. data/lib/bcdd/result/{transitions → event_logs}/tree.rb +27 -11
  60. data/lib/bcdd/result/event_logs.rb +27 -0
  61. data/lib/bcdd/result/failure.rb +1 -3
  62. data/lib/bcdd/result/success.rb +1 -3
  63. data/lib/bcdd/result/version.rb +1 -1
  64. data/lib/bcdd/result.rb +23 -191
  65. data/lib/bcdd/success.rb +23 -0
  66. data/sig/bcdd/context.rbs +175 -0
  67. data/sig/bcdd/failure.rbs +13 -0
  68. data/sig/bcdd/result/config.rbs +1 -3
  69. data/sig/bcdd/result/context.rbs +2 -174
  70. data/sig/bcdd/result/contract.rbs +1 -0
  71. data/sig/bcdd/result/{transitions.rbs → event_logs.rbs} +19 -19
  72. data/sig/bcdd/result.rbs +13 -31
  73. data/sig/bcdd/success.rbs +13 -0
  74. metadata +41 -24
  75. data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +0 -28
  76. data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +0 -54
  77. data/lib/bcdd/result/context/failure.rb +0 -9
  78. data/lib/bcdd/result/context.rb +0 -93
  79. data/lib/bcdd/result/failure/methods.rb +0 -21
  80. data/lib/bcdd/result/success/methods.rb +0 -21
  81. data/lib/bcdd/result/transitions.rb +0 -27
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcdd-result
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-01 00:00:00.000000000 Z
11
+ date: 2024-03-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Unleash a pragmatic and observable use of Result Pattern and Railway-Oriented
14
14
  Programming in Ruby.
@@ -38,10 +38,23 @@ files:
38
38
  - examples/multiple_listeners/config/boot.rb
39
39
  - examples/multiple_listeners/config/initializers/bcdd.rb
40
40
  - examples/multiple_listeners/db/setup.rb
41
+ - examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb
41
42
  - examples/multiple_listeners/lib/bcdd/result/rollback_on_failure.rb
42
- - examples/multiple_listeners/lib/bcdd/result/transitions_record.rb
43
+ - examples/multiple_listeners/lib/event_logs_listener/stdout.rb
43
44
  - examples/multiple_listeners/lib/runtime_breaker.rb
44
- - examples/multiple_listeners/lib/transitions_listener/stdout.rb
45
+ - examples/service_objects/Rakefile
46
+ - examples/service_objects/app/models/account.rb
47
+ - examples/service_objects/app/models/account/member.rb
48
+ - examples/service_objects/app/models/user.rb
49
+ - examples/service_objects/app/models/user/token.rb
50
+ - examples/service_objects/app/services/account/owner_creation.rb
51
+ - examples/service_objects/app/services/application_service.rb
52
+ - examples/service_objects/app/services/user/creation.rb
53
+ - examples/service_objects/app/services/user/token/creation.rb
54
+ - examples/service_objects/config.rb
55
+ - examples/service_objects/config/boot.rb
56
+ - examples/service_objects/config/initializers/bcdd.rb
57
+ - examples/service_objects/db/setup.rb
45
58
  - examples/single_listener/Rakefile
46
59
  - examples/single_listener/app/models/account.rb
47
60
  - examples/single_listener/app/models/account/member.rb
@@ -56,9 +69,18 @@ files:
56
69
  - examples/single_listener/db/setup.rb
57
70
  - examples/single_listener/lib/bcdd/result/rollback_on_failure.rb
58
71
  - examples/single_listener/lib/runtime_breaker.rb
59
- - examples/single_listener/lib/single_transitions_listener.rb
72
+ - examples/single_listener/lib/single_event_logs_listener.rb
60
73
  - lib/bcdd-result.rb
74
+ - lib/bcdd/context.rb
75
+ - lib/bcdd/context/callable_and_then.rb
76
+ - lib/bcdd/context/expectations.rb
77
+ - lib/bcdd/context/expectations/mixin.rb
78
+ - lib/bcdd/context/failure.rb
79
+ - lib/bcdd/context/mixin.rb
80
+ - lib/bcdd/context/success.rb
81
+ - lib/bcdd/failure.rb
61
82
  - lib/bcdd/result.rb
83
+ - lib/bcdd/result/_self.rb
62
84
  - lib/bcdd/result/callable_and_then.rb
63
85
  - lib/bcdd/result/callable_and_then/caller.rb
64
86
  - lib/bcdd/result/callable_and_then/config.rb
@@ -70,13 +92,6 @@ files:
70
92
  - lib/bcdd/result/config/switchers/constant_aliases.rb
71
93
  - lib/bcdd/result/config/switchers/features.rb
72
94
  - lib/bcdd/result/config/switchers/pattern_matching.rb
73
- - lib/bcdd/result/context.rb
74
- - lib/bcdd/result/context/callable_and_then.rb
75
- - lib/bcdd/result/context/expectations.rb
76
- - lib/bcdd/result/context/expectations/mixin.rb
77
- - lib/bcdd/result/context/failure.rb
78
- - lib/bcdd/result/context/mixin.rb
79
- - lib/bcdd/result/context/success.rb
80
95
  - lib/bcdd/result/contract.rb
81
96
  - lib/bcdd/result/contract/disabled.rb
82
97
  - lib/bcdd/result/contract/error.rb
@@ -87,25 +102,26 @@ files:
87
102
  - lib/bcdd/result/contract/type_checker.rb
88
103
  - lib/bcdd/result/data.rb
89
104
  - lib/bcdd/result/error.rb
105
+ - lib/bcdd/result/event_logs.rb
106
+ - lib/bcdd/result/event_logs/config.rb
107
+ - lib/bcdd/result/event_logs/listener.rb
108
+ - lib/bcdd/result/event_logs/listeners.rb
109
+ - lib/bcdd/result/event_logs/tracking.rb
110
+ - lib/bcdd/result/event_logs/tracking/disabled.rb
111
+ - lib/bcdd/result/event_logs/tracking/enabled.rb
112
+ - lib/bcdd/result/event_logs/tree.rb
90
113
  - lib/bcdd/result/expectations.rb
91
114
  - lib/bcdd/result/expectations/mixin.rb
92
115
  - lib/bcdd/result/failure.rb
93
- - lib/bcdd/result/failure/methods.rb
94
116
  - lib/bcdd/result/handler.rb
95
117
  - lib/bcdd/result/handler/allowed_types.rb
96
118
  - lib/bcdd/result/ignored_types.rb
97
119
  - lib/bcdd/result/mixin.rb
98
120
  - lib/bcdd/result/success.rb
99
- - lib/bcdd/result/success/methods.rb
100
- - lib/bcdd/result/transitions.rb
101
- - lib/bcdd/result/transitions/config.rb
102
- - lib/bcdd/result/transitions/listener.rb
103
- - lib/bcdd/result/transitions/listeners.rb
104
- - lib/bcdd/result/transitions/tracking.rb
105
- - lib/bcdd/result/transitions/tracking/disabled.rb
106
- - lib/bcdd/result/transitions/tracking/enabled.rb
107
- - lib/bcdd/result/transitions/tree.rb
108
121
  - lib/bcdd/result/version.rb
122
+ - lib/bcdd/success.rb
123
+ - sig/bcdd/context.rbs
124
+ - sig/bcdd/failure.rbs
109
125
  - sig/bcdd/result.rbs
110
126
  - sig/bcdd/result/callable_and_then.rbs
111
127
  - sig/bcdd/result/config.rbs
@@ -113,12 +129,13 @@ files:
113
129
  - sig/bcdd/result/contract.rbs
114
130
  - sig/bcdd/result/data.rbs
115
131
  - sig/bcdd/result/error.rbs
132
+ - sig/bcdd/result/event_logs.rbs
116
133
  - sig/bcdd/result/expectations.rbs
117
134
  - sig/bcdd/result/handler.rbs
118
135
  - sig/bcdd/result/ignored_types.rbs
119
136
  - sig/bcdd/result/mixin.rbs
120
- - sig/bcdd/result/transitions.rbs
121
137
  - sig/bcdd/result/version.rbs
138
+ - sig/bcdd/success.rbs
122
139
  homepage: https://github.com/b-cdd/result
123
140
  licenses:
124
141
  - MIT
@@ -143,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
160
  - !ruby/object:Gem::Version
144
161
  version: '0'
145
162
  requirements: []
146
- rubygems_version: 3.5.3
163
+ rubygems_version: 3.5.6
147
164
  signing_key:
148
165
  specification_version: 4
149
166
  summary: Unleash a pragmatic and observable use of Result Pattern and Railway-Oriented
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result::TransitionsRecord < ActiveRecord::Base
4
- self.table_name = 'bcdd_result_transitions'
5
-
6
- class Listener
7
- include ::BCDD::Result::Transitions::Listener
8
-
9
- def on_finish(transitions:)
10
- metadata = transitions[:metadata]
11
- root_name = transitions.dig(:records, 0, :root, :name) || 'Unknown'
12
-
13
- BCDD::Result::TransitionsRecord.create(
14
- root_name: root_name,
15
- trace_id: metadata[:trace_id],
16
- version: transitions[:version],
17
- duration: metadata[:duration],
18
- ids_tree: metadata[:ids_tree],
19
- ids_matrix: metadata[:ids_matrix],
20
- records: transitions[:records]
21
- )
22
- rescue ::StandardError => e
23
- err = "#{e.message} (#{e.class}); Backtrace: #{e.backtrace.join(', ')}"
24
-
25
- ::Kernel.warn "Error on BCDD::Result::TransitionsRecord::Listener#on_finish: #{err}"
26
- end
27
- end
28
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class TransitionsListener::Stdout
4
- include BCDD::Result::Transitions::Listener
5
-
6
- def initialize
7
- @buffer = []
8
- end
9
-
10
- def on_start(scope:)
11
- scope => { id:, name:, desc: }
12
-
13
- @buffer << [id, "##{id} #{name} - #{desc}".chomp('- ')]
14
- end
15
-
16
- def on_record(record:)
17
- record => { current: { id: }, result: { kind:, type: } }
18
-
19
- method_name = record.dig(:and_then, :method_name)
20
-
21
- @buffer << [id, " * #{kind}(#{type}) from method: #{method_name}".chomp('from method: ')]
22
- end
23
-
24
- MapNestedMessages = ->(transitions, buffer, hide_given_and_continue) do
25
- ids_matrix = transitions.dig(:metadata, :ids_matrix)
26
-
27
- messages = buffer.filter_map { |(id, msg)| "#{' ' * ids_matrix[id].last}#{msg}" if ids_matrix[id] }
28
-
29
- messages.reject! { _1.match?(/\(_(given|continue)_\)/) } if hide_given_and_continue
30
-
31
- messages
32
- end
33
-
34
- def on_finish(transitions:)
35
- messages = MapNestedMessages[transitions, @buffer, ENV['HIDE_GIVEN_AND_CONTINUE']]
36
-
37
- puts messages.join("\n")
38
- end
39
-
40
- def before_interruption(exception:, transitions:)
41
- messages = MapNestedMessages[transitions, @buffer, ENV['HIDE_GIVEN_AND_CONTINUE']]
42
-
43
- puts messages.join("\n")
44
-
45
- bc = ::ActiveSupport::BacktraceCleaner.new
46
- bc.add_filter { |line| line.gsub(__dir__.sub('/lib', ''), '').sub(/\A\//, '')}
47
- bc.add_silencer { |line| /lib\/bcdd\/result/.match?(line) }
48
- bc.add_silencer { |line| line.include?(RUBY_VERSION) }
49
-
50
- backtrace = bc.clean(exception.backtrace)
51
-
52
- puts "\nException: #{exception.message} (#{exception.class}); Backtrace: #{backtrace.join(", ")}"
53
- end
54
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result::Context::Failure < BCDD::Result::Context
4
- include BCDD::Result::Failure::Methods
5
-
6
- def and_expose(_type, _keys, **_options)
7
- self
8
- end
9
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result
4
- class Context < self
5
- require_relative 'context/failure'
6
- require_relative 'context/success'
7
- require_relative 'context/mixin'
8
- require_relative 'context/expectations'
9
- require_relative 'context/callable_and_then'
10
-
11
- EXPECTED_OUTCOME = 'BCDD::Result::Context::Success or BCDD::Result::Context::Failure'
12
-
13
- def self.Success(type, **value)
14
- Success.new(type: type, value: value)
15
- end
16
-
17
- def self.Failure(type, **value)
18
- Failure.new(type: type, value: value)
19
- end
20
-
21
- def initialize(type:, value:, source: nil, expectations: nil, terminal: nil)
22
- value.is_a?(::Hash) or raise ::ArgumentError, 'value must be a Hash'
23
-
24
- @acc = {}
25
-
26
- super
27
- end
28
-
29
- def and_then(method_name = nil, **injected_value, &block)
30
- super(method_name, injected_value, &block)
31
- end
32
-
33
- def and_then!(source, **injected_value)
34
- _call = injected_value.delete(:_call)
35
-
36
- acc.merge!(injected_value)
37
-
38
- super(source, injected_value, _call: _call)
39
- end
40
-
41
- protected
42
-
43
- attr_reader :acc
44
-
45
- private
46
-
47
- SourceMethodArity = ->(method) do
48
- return 0 if method.arity.zero?
49
-
50
- parameters = method.parameters.map(&:first)
51
-
52
- return 1 if !parameters.empty? && parameters.all?(/\Akey/)
53
-
54
- -1
55
- end
56
-
57
- def call_and_then_source_method!(method, injected_value)
58
- acc.merge!(value.merge(injected_value))
59
-
60
- case SourceMethodArity[method]
61
- when 0 then source.send(method.name)
62
- when 1 then source.send(method.name, **acc)
63
- else raise Error::InvalidSourceMethodArity.build(source: source, method: method, max_arity: 1)
64
- end
65
- end
66
-
67
- def call_and_then_block!(block)
68
- acc.merge!(value)
69
-
70
- block.call(acc)
71
- end
72
-
73
- def call_and_then_callable!(source, value:, injected_value:, method_name:)
74
- acc.merge!(value.merge(injected_value))
75
-
76
- CallableAndThen::Caller.call(source, value: acc, injected_value: injected_value, method_name: method_name)
77
- end
78
-
79
- def ensure_result_object(result, origin:)
80
- raise_unexpected_outcome_error(result, origin) unless result.is_a?(Context)
81
-
82
- return result.tap { _1.acc.merge!(acc) } if result.source.equal?(source)
83
-
84
- raise Error::InvalidResultSource.build(given_result: result, expected_source: source)
85
- end
86
-
87
- def raise_unexpected_outcome_error(result, origin)
88
- raise Error::UnexpectedOutcome.build(outcome: result, origin: origin, expected: EXPECTED_OUTCOME)
89
- end
90
-
91
- private_constant :SourceMethodArity
92
- end
93
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BCDD::Result::Failure::Methods
4
- def success?(_type = nil)
5
- false
6
- end
7
-
8
- def failure?(type = nil)
9
- type.nil? || type_checker.allow_failure?([type])
10
- end
11
-
12
- def value_or
13
- yield(value)
14
- end
15
-
16
- private
17
-
18
- def kind
19
- :failure
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BCDD::Result::Success::Methods
4
- def success?(type = nil)
5
- type.nil? || type_checker.allow_success?([type])
6
- end
7
-
8
- def failure?(_type = nil)
9
- false
10
- end
11
-
12
- def value_or
13
- value
14
- end
15
-
16
- private
17
-
18
- def kind
19
- :success
20
- end
21
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result
4
- module Transitions
5
- require_relative 'transitions/listener'
6
- require_relative 'transitions/listeners'
7
- require_relative 'transitions/config'
8
- require_relative 'transitions/tree'
9
- require_relative 'transitions/tracking'
10
-
11
- THREAD_VAR_NAME = :bcdd_result_transitions_tracking
12
-
13
- EnsureResult = ->(result) do
14
- return result if result.is_a?(::BCDD::Result)
15
-
16
- raise Error::UnexpectedOutcome.build(outcome: result, origin: :transitions)
17
- end
18
-
19
- def self.tracking
20
- Thread.current[THREAD_VAR_NAME] ||= Tracking.instance
21
- end
22
- end
23
-
24
- def self.transitions(name: nil, desc: nil, &block)
25
- Transitions.tracking.exec(name, desc, &block)
26
- end
27
- end