bcdd-process 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/CHANGELOG.md +21 -0
- data/examples/business_processes/app/models/account/owner_creation.rb +1 -1
- data/examples/business_processes/app/models/user/creation.rb +1 -1
- data/examples/business_processes/config.rb +1 -0
- data/examples/business_processes/lib/bcdd/contracts.rb +0 -2
- data/examples/business_processes/lib/bcdd/values/uuid.rb +21 -0
- data/lib/bcdd/ext/contract/respond_to.rb +48 -0
- data/lib/bcdd/ext/contract.rb +16 -0
- data/lib/bcdd/ext/data.rb +94 -0
- data/lib/bcdd/ext/value.rb +151 -0
- data/lib/bcdd/process/output.rb +54 -0
- data/lib/bcdd/process/version.rb +1 -1
- data/lib/bcdd/process.rb +35 -36
- metadata +10 -7
- data/lib/bcdd/process/caller.rb +0 -37
- data/lib/bcdd/process/input_spec.rb +0 -66
- data/lib/bcdd/process/output_spec.rb +0 -31
- /data/lib/bcdd/{contract → ext/contract}/null.rb +0 -0
- /data/lib/bcdd/{contracts.rb → ext/contracts.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: 60c6b5184edd4076e88382736efff9e0981be518c064ae290a75ad4d052d3196
|
4
|
+
data.tar.gz: ca15261b4991198f5277cddf5f2c2133458e7163f8388e39d5a0c18dad688bce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4dd1a4bf3e06a13060233215ea6ad8ee1f0a0a6a4be94d202a6126833fe62a68504a4af677f2f4a8b34abb39a3124a6b8d25009569dfa2d3050debaad45dbd9b
|
7
|
+
data.tar.gz: '08daaa2746fd38c0db77c1d131080923693c697d19577d2b33dded81f1a9675c4a841650bba799c46b24a2e8ba6de06c4370ba143ab7b65578ab0fb90eddac84'
|
data/.rubocop.yml
CHANGED
@@ -49,6 +49,9 @@ Style/ParallelAssignment:
|
|
49
49
|
Style/SingleLineMethods:
|
50
50
|
Enabled: false
|
51
51
|
|
52
|
+
Style/FormatStringToken:
|
53
|
+
Enabled: false
|
54
|
+
|
52
55
|
Style/MapToSet:
|
53
56
|
Enabled: false
|
54
57
|
|
@@ -64,6 +67,10 @@ Naming/VariableName:
|
|
64
67
|
Naming/MemoizedInstanceVariableName:
|
65
68
|
Enabled: false
|
66
69
|
|
70
|
+
Metrics/AbcSize:
|
71
|
+
Exclude:
|
72
|
+
- lib/bcdd/ext/value.rb
|
73
|
+
|
67
74
|
Metrics/BlockLength:
|
68
75
|
Exclude:
|
69
76
|
- test/**/*.rb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.4.0] - 2024-02-04
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Add `:value` input property to use a registered `BCDD::Value` to handle the input.
|
8
|
+
```ruby
|
9
|
+
attribute :name, value: :name
|
10
|
+
```
|
11
|
+
|
12
|
+
- Add `:respond_to` input property to check if the value responds to a given method.
|
13
|
+
```ruby
|
14
|
+
attribute :name, respond_to: :strip
|
15
|
+
```
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- Use `:type` property to check if the normalize should be applied.
|
20
|
+
```ruby
|
21
|
+
attribute :name, type: String, normalize: -> { _1.strip }
|
22
|
+
```
|
23
|
+
|
3
24
|
## [0.3.1] - 2024-02-03
|
4
25
|
|
5
26
|
### Fixed
|
@@ -5,7 +5,7 @@ class Account
|
|
5
5
|
include BCDD::Result::RollbackOnFailure
|
6
6
|
|
7
7
|
input do
|
8
|
-
attribute :uuid,
|
8
|
+
attribute :uuid, value: :uuid
|
9
9
|
attribute :owner, type: ::Hash, contract: :is_present
|
10
10
|
end
|
11
11
|
|
@@ -5,7 +5,7 @@ class User
|
|
5
5
|
include BCDD::Result::RollbackOnFailure
|
6
6
|
|
7
7
|
input do
|
8
|
-
attribute :uuid,
|
8
|
+
attribute :uuid, value: :uuid
|
9
9
|
attribute :name, contract: :is_str, normalize: -> { _1.strip.gsub(/\s+/, ' ') }
|
10
10
|
attribute :email, contract: :is_email, normalize: -> { _1.strip.downcase }
|
11
11
|
attribute :password, contract: :is_password
|
@@ -4,14 +4,12 @@ module BCDD::Contracts
|
|
4
4
|
HasSize = ->(min, max) { ->(val) { val.size.between?(min, max) or "must be >= #{min} and <= #{max} chars" } }
|
5
5
|
|
6
6
|
is_str = contract[::String]
|
7
|
-
is_uuid = ->(val) { val.match?(/\A[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\z/) or '%p must be an UUID' }
|
8
7
|
is_email = ->(val) { val.match?(::URI::MailTo::EMAIL_REGEXP) or '%p must be an email' }
|
9
8
|
is_present = ->(val) { val.present? or '%p must be present' }
|
10
9
|
is_persisted = ->(val) { val.persisted? or '%p must be persisted' }
|
11
10
|
|
12
11
|
register(
|
13
12
|
is_str: is_str,
|
14
|
-
is_uuid: is_str & is_present & is_uuid,
|
15
13
|
is_email: is_str & is_present& is_email,
|
16
14
|
is_present: is_present,
|
17
15
|
is_password: is_str & is_present & HasSize[8, 72],
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../contracts'
|
4
|
+
|
5
|
+
module BCDD
|
6
|
+
module Contracts
|
7
|
+
is_uuid = ->(val) { val.match?(/\A[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\z/) or '%p must be an UUID' }
|
8
|
+
|
9
|
+
register(is_uuid: contract[::String] & :is_present & is_uuid)
|
10
|
+
end
|
11
|
+
|
12
|
+
module Values
|
13
|
+
register(
|
14
|
+
name: :uuid,
|
15
|
+
type: ::String,
|
16
|
+
contract: :is_uuid,
|
17
|
+
normalize: -> { _1.strip.downcase },
|
18
|
+
default: -> { ::SecureRandom.uuid }
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDD::Contract
|
4
|
+
# TODO: Move to bcdd-contract
|
5
|
+
module RespondTo
|
6
|
+
class Checking
|
7
|
+
include Core::Checking
|
8
|
+
|
9
|
+
def initialize(method_names, value)
|
10
|
+
@value = value
|
11
|
+
@errors = []
|
12
|
+
|
13
|
+
validate(method_names, @errors)
|
14
|
+
end
|
15
|
+
|
16
|
+
def errors_message
|
17
|
+
valid? ? '' : errors[0]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def validate(method_names, errors)
|
23
|
+
return if method_names.all? { |method_name| value.respond_to?(method_name) }
|
24
|
+
|
25
|
+
errors << format('%p must respond to %p', value, method_names)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module Checker
|
30
|
+
include Core::Checker
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.new(args)
|
34
|
+
args.is_a?(Array) or raise ::ArgumentError, format('%p must be an array', args)
|
35
|
+
|
36
|
+
raise ::ArgumentError, "Must provide at least one symbol #{args.inspect}" if args.empty? || !args.all?(::Symbol)
|
37
|
+
|
38
|
+
Core::Factory.new(Checker, Checking, args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# TODO: Move to bcdd-contract
|
43
|
+
def self.respond_to(args)
|
44
|
+
RespondTo.new(args)
|
45
|
+
end
|
46
|
+
|
47
|
+
private_constant :RespondTo
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bcdd/contract'
|
4
|
+
|
5
|
+
require_relative 'contracts'
|
6
|
+
require_relative 'contract/null'
|
7
|
+
require_relative 'contract/respond_to'
|
8
|
+
|
9
|
+
module BCDD::Contract
|
10
|
+
# TODO: Move to bcdd-contract
|
11
|
+
def self.type(arg)
|
12
|
+
arg.is_a?(::Module) or raise ::ArgumentError, format('%p must be a class OR module', arg)
|
13
|
+
|
14
|
+
unit(arg)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
|
5
|
+
module BCDD
|
6
|
+
class Data
|
7
|
+
class Object
|
8
|
+
attr_reader :attributes, :errors
|
9
|
+
|
10
|
+
def initialize(**kargs)
|
11
|
+
properties = self.class::Properties
|
12
|
+
attributes = properties.map(kargs)
|
13
|
+
|
14
|
+
@errors = {}
|
15
|
+
@attributes =
|
16
|
+
if properties.contract?
|
17
|
+
attributes.each_with_object({}) do |(key, value), output|
|
18
|
+
output[key] = value.valid? ? value.value : (errors[key] = value.errors)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
attributes.transform_values!(&:value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Properties
|
27
|
+
attr_reader :spec, :contract
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@spec = {}
|
31
|
+
@contract = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def attribute(name, **options)
|
35
|
+
name.is_a?(Symbol) or raise ArgumentError, "#{name.inspect} must be a Symbol"
|
36
|
+
|
37
|
+
value_option = options[:value]
|
38
|
+
|
39
|
+
spec[name] =
|
40
|
+
if value_option
|
41
|
+
(value_option.is_a?(Value::Object) ? value_option : Value[value_option])::Properties
|
42
|
+
else
|
43
|
+
Value::Properties.new(options).freeze
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def freeze
|
48
|
+
@contract = spec.any? { |_, properties| properties.contract? }
|
49
|
+
|
50
|
+
spec.freeze
|
51
|
+
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
def contract?
|
56
|
+
contract
|
57
|
+
end
|
58
|
+
|
59
|
+
def map(input)
|
60
|
+
spec.each_with_object({}) do |(name, properties), output|
|
61
|
+
output[name] = properties.map(input[name])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Evaluator
|
67
|
+
# :nodoc:
|
68
|
+
attr_reader :properties
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
@properties = Data::Properties.new
|
72
|
+
end
|
73
|
+
|
74
|
+
def attribute(name, **options)
|
75
|
+
properties.attribute(name, **options)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def contract
|
81
|
+
BCDD::Contract
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.new(&block)
|
86
|
+
evaluator = Evaluator.new
|
87
|
+
evaluator.instance_eval(&block)
|
88
|
+
|
89
|
+
klass = ::Class.new(Object)
|
90
|
+
klass.const_set(:Properties, evaluator.properties.freeze)
|
91
|
+
klass
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module BCDD
|
6
|
+
class Value
|
7
|
+
class Object
|
8
|
+
attr_reader :value, :errors
|
9
|
+
|
10
|
+
def initialize(value = nil)
|
11
|
+
properties = self.class::Properties
|
12
|
+
contract = properties.map(value)
|
13
|
+
|
14
|
+
@errors = contract.errors
|
15
|
+
@value = contract.value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Properties
|
20
|
+
module Contract
|
21
|
+
def self.[](options)
|
22
|
+
contract = compose(options)
|
23
|
+
required = options.fetch(:required, true)
|
24
|
+
|
25
|
+
if contract
|
26
|
+
required ? contract : (contract | nil)
|
27
|
+
elsif required
|
28
|
+
Contracts::NotNil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.compose(options)
|
33
|
+
type = ::BCDD::Contract.type(options[:type]) if options.key?(:type)
|
34
|
+
contract = ::BCDD::Contract[options[:contract]] if options.key?(:contract)
|
35
|
+
respond_to = ::BCDD::Contract.respond_to(Array(options[:respond_to])) if options.key?(:respond_to)
|
36
|
+
|
37
|
+
[type, contract, respond_to].compact!&.reduce(:&)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Default = ->(options) do
|
42
|
+
value = options[:default]
|
43
|
+
|
44
|
+
return value unless value.is_a?(Proc)
|
45
|
+
return value if value.lambda? && value.arity.zero?
|
46
|
+
|
47
|
+
raise ArgumentError, 'Default value must be a lambda with zero arity'
|
48
|
+
end
|
49
|
+
|
50
|
+
Normalize = ->(options) do
|
51
|
+
value = options[:normalize]
|
52
|
+
|
53
|
+
return value if value.is_a?(Proc)
|
54
|
+
|
55
|
+
raise ArgumentError, 'normalize value must be a lambda'
|
56
|
+
end
|
57
|
+
|
58
|
+
Type = ->(options) do
|
59
|
+
type = options[:type]
|
60
|
+
|
61
|
+
return type if type.is_a?(::Module)
|
62
|
+
|
63
|
+
raise ArgumentError, 'type must be a Module or a Class'
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :spec, :contract
|
67
|
+
|
68
|
+
def initialize(options)
|
69
|
+
@contract = false
|
70
|
+
|
71
|
+
contract = Contract[options]
|
72
|
+
|
73
|
+
@spec = {}
|
74
|
+
@spec[:type] = Type[options] if options.key?(:type)
|
75
|
+
@spec[:default] = Default[options] if options.key?(:default)
|
76
|
+
@spec[:contract] = contract if contract
|
77
|
+
@spec[:normalize] = Normalize[options] if options.key?(:normalize)
|
78
|
+
end
|
79
|
+
|
80
|
+
def freeze
|
81
|
+
@contract = spec.key?(:contract)
|
82
|
+
|
83
|
+
spec.freeze
|
84
|
+
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
def contract?
|
89
|
+
contract
|
90
|
+
end
|
91
|
+
|
92
|
+
def map(value)
|
93
|
+
if !value && spec.key?(:default)
|
94
|
+
default = spec[:default]
|
95
|
+
|
96
|
+
value = default.is_a?(::Proc) ? default.call : default
|
97
|
+
end
|
98
|
+
|
99
|
+
type = spec[:type]
|
100
|
+
|
101
|
+
value = spec[:normalize].call(value) if spec.key?(:normalize) && (!type || type === value)
|
102
|
+
|
103
|
+
spec.key?(:contract) ? spec[:contract][value] : Contract.null(value)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Registry
|
108
|
+
include ::Singleton
|
109
|
+
|
110
|
+
attr_reader :registry
|
111
|
+
|
112
|
+
def initialize
|
113
|
+
@registry = {}
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.write(options)
|
117
|
+
name = options.delete(:name)
|
118
|
+
|
119
|
+
name.is_a?(Symbol) or raise ArgumentError, "#{name.inspect} must be a Symbol"
|
120
|
+
|
121
|
+
instance.registry[name] = Value.new(**options)
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.read(name)
|
125
|
+
value_object = instance.registry[name]
|
126
|
+
|
127
|
+
value_object or raise ArgumentError, "#{name.inspect} is not registered"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.new(**options)
|
132
|
+
klass = ::Class.new(Object)
|
133
|
+
klass.const_set(:Properties, Properties.new(options).freeze)
|
134
|
+
klass
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.[](name)
|
138
|
+
Registry.read(name)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
module Values
|
143
|
+
class << self
|
144
|
+
private
|
145
|
+
|
146
|
+
def register(**options)
|
147
|
+
Value::Registry.write(options)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDD
|
4
|
+
class Process
|
5
|
+
module Output
|
6
|
+
# :nodoc:
|
7
|
+
class Properties
|
8
|
+
attr_reader :success
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@success = {}
|
12
|
+
@failure = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def success=(spec)
|
16
|
+
@success = spec.transform_values(&BCDD::Contract)
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure=(spec)
|
20
|
+
@failure = spec.transform_values(&BCDD::Contract)
|
21
|
+
end
|
22
|
+
|
23
|
+
INVALID_INPUT = { invalid_input: ::Hash }.freeze
|
24
|
+
|
25
|
+
def failure
|
26
|
+
INVALID_INPUT.merge(@failure)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Evaluator
|
31
|
+
# :nodoc:
|
32
|
+
attr_reader :__properties__
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@__properties__ = Properties.new
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def Success(**spec)
|
41
|
+
__properties__.success = spec
|
42
|
+
end
|
43
|
+
|
44
|
+
def Failure(**spec)
|
45
|
+
__properties__.failure = spec
|
46
|
+
end
|
47
|
+
|
48
|
+
def contract
|
49
|
+
::BCDD::Contract
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/bcdd/process/version.rb
CHANGED
data/lib/bcdd/process.rb
CHANGED
@@ -1,60 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bcdd/result'
|
4
|
-
require 'bcdd/contract'
|
5
4
|
|
6
|
-
require_relative '
|
7
|
-
require_relative '
|
5
|
+
require_relative 'ext/contract'
|
6
|
+
require_relative 'ext/data'
|
8
7
|
|
9
8
|
require_relative 'process/version'
|
10
|
-
require_relative 'process/
|
11
|
-
require_relative 'process/input_spec'
|
12
|
-
require_relative 'process/output_spec'
|
9
|
+
require_relative 'process/output'
|
13
10
|
|
14
11
|
module BCDD
|
15
12
|
class Process
|
16
|
-
|
17
|
-
|
13
|
+
module Caller
|
14
|
+
def call(**kargs)
|
15
|
+
input = self.class::Input.new(**kargs)
|
18
16
|
|
19
|
-
|
20
|
-
|
17
|
+
Result.transitions(name: self.class.name) do
|
18
|
+
return Failure(:invalid_input, **input.errors) if input.errors.any?
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
spec.__result__.transform_values!(&:freeze).freeze
|
25
|
-
|
26
|
-
@__input_contract__ = spec.__result__.any? { |_key, value| value.key?(:contract) }
|
27
|
-
@__input__ = spec.__result__
|
20
|
+
super(**input.attributes)
|
21
|
+
end
|
28
22
|
end
|
23
|
+
end
|
29
24
|
|
30
|
-
|
31
|
-
|
25
|
+
def self.input(&block)
|
26
|
+
return if const_defined?(:Input)
|
32
27
|
|
33
|
-
|
28
|
+
const_set(:Input, ::BCDD::Data.new(&block))
|
29
|
+
end
|
34
30
|
|
35
|
-
|
36
|
-
spec = OutputSpec.new
|
37
|
-
spec.instance_eval(&block)
|
31
|
+
RESULT_CONFIG = { addon: { given: true, continue: true }.freeze }.freeze
|
38
32
|
|
39
|
-
|
40
|
-
|
41
|
-
failure = output.fetch(:failure, {}).merge(invalid_input: ::Hash)
|
33
|
+
def self.output(expectations: true, &block)
|
34
|
+
return if const_defined?(:Result, false)
|
42
35
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
36
|
+
if expectations
|
37
|
+
evaluator = Output::Evaluator.new
|
38
|
+
evaluator.instance_eval(&block)
|
47
39
|
|
48
|
-
|
49
|
-
|
40
|
+
success = evaluator.__properties__.success
|
41
|
+
failure = evaluator.__properties__.failure
|
50
42
|
|
51
|
-
|
52
|
-
|
43
|
+
include(Result::Context::Expectations.mixin(config: RESULT_CONFIG, success: success, failure: failure))
|
44
|
+
else
|
45
|
+
include(Result::Context.mixin(config: RESULT_CONFIG))
|
53
46
|
end
|
47
|
+
end
|
54
48
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
49
|
+
def self.inherited(subclass)
|
50
|
+
subclass.prepend(Caller)
|
58
51
|
end
|
52
|
+
|
53
|
+
def self.call(**input)
|
54
|
+
new.call(**input)
|
55
|
+
end
|
56
|
+
|
57
|
+
private_constant :Caller, :RESULT_CONFIG
|
59
58
|
end
|
60
59
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bcdd-process
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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-
|
11
|
+
date: 2024-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bcdd-contract
|
@@ -68,15 +68,18 @@ files:
|
|
68
68
|
- examples/business_processes/lib/bcdd/contracts.rb
|
69
69
|
- examples/business_processes/lib/bcdd/result/rollback_on_failure.rb
|
70
70
|
- examples/business_processes/lib/bcdd/result/transitions_record.rb
|
71
|
+
- examples/business_processes/lib/bcdd/values/uuid.rb
|
71
72
|
- examples/business_processes/lib/runtime_breaker.rb
|
72
73
|
- examples/business_processes/lib/transitions_listener/stdout.rb
|
73
74
|
- lib/bcdd-process.rb
|
74
|
-
- lib/bcdd/contract
|
75
|
-
- lib/bcdd/
|
75
|
+
- lib/bcdd/ext/contract.rb
|
76
|
+
- lib/bcdd/ext/contract/null.rb
|
77
|
+
- lib/bcdd/ext/contract/respond_to.rb
|
78
|
+
- lib/bcdd/ext/contracts.rb
|
79
|
+
- lib/bcdd/ext/data.rb
|
80
|
+
- lib/bcdd/ext/value.rb
|
76
81
|
- lib/bcdd/process.rb
|
77
|
-
- lib/bcdd/process/
|
78
|
-
- lib/bcdd/process/input_spec.rb
|
79
|
-
- lib/bcdd/process/output_spec.rb
|
82
|
+
- lib/bcdd/process/output.rb
|
80
83
|
- lib/bcdd/process/version.rb
|
81
84
|
- sig/bcdd/process.rbs
|
82
85
|
homepage: https://github.com/b-cdd/process
|
data/lib/bcdd/process/caller.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module BCDD
|
4
|
-
class Process
|
5
|
-
module Caller
|
6
|
-
PrepareInputs = ->(spec, input) do
|
7
|
-
spec.each_with_object({}) do |(name, options), result|
|
8
|
-
value = input.fetch(name) do
|
9
|
-
if options.key?(:default)
|
10
|
-
default = options[:default]
|
11
|
-
|
12
|
-
default.is_a?(::Proc) ? default.call : default
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
value = options[:normalize].call(value) if options.key?(:normalize)
|
17
|
-
|
18
|
-
result[name] = options.key?(:contract) ? options[:contract][value] : Contract.null(value)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def call(**inputs)
|
23
|
-
prepared_input = PrepareInputs[self.class.__input__, inputs]
|
24
|
-
|
25
|
-
Result.transitions(name: self.class.name) do
|
26
|
-
if self.class.__input_contract__
|
27
|
-
invalid_input = prepared_input.select { |_key, value| value.invalid? }
|
28
|
-
|
29
|
-
return Failure(:invalid_input, **invalid_input.transform_values(&:errors)) unless invalid_input.empty?
|
30
|
-
end
|
31
|
-
|
32
|
-
super(**prepared_input.transform_values!(&:value))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module BCDD
|
4
|
-
class Process
|
5
|
-
class InputSpec
|
6
|
-
module MapContract
|
7
|
-
def self.[](options)
|
8
|
-
required = options.fetch(:required, true)
|
9
|
-
|
10
|
-
if options.key?(:contract) || options.key?(:type) || options.key?(:validate)
|
11
|
-
resolve(options).then { required ? _1 : (_1 | nil) }
|
12
|
-
elsif required
|
13
|
-
Contracts::NotNil
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.resolve(options)
|
18
|
-
type = ::BCDD::Contract.unit(options[:type]) if options.key?(:type)
|
19
|
-
contract = ::BCDD::Contract[options[:contract]] if options.key?(:contract)
|
20
|
-
|
21
|
-
type && contract ? (type & contract) : type || contract
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
MapDefault = ->(options) do
|
26
|
-
value = options[:default]
|
27
|
-
|
28
|
-
return value unless value.is_a?(Proc)
|
29
|
-
return value if value.lambda? && value.arity.zero?
|
30
|
-
|
31
|
-
raise ArgumentError, 'Default value must be a lambda with zero arity'
|
32
|
-
end
|
33
|
-
|
34
|
-
MapNormalize = ->(options) do
|
35
|
-
value = options[:normalize]
|
36
|
-
|
37
|
-
return value if value.is_a?(Proc)
|
38
|
-
|
39
|
-
raise ArgumentError, 'normalize value must be a lambda'
|
40
|
-
end
|
41
|
-
|
42
|
-
# :nodoc:
|
43
|
-
attr_reader :__result__
|
44
|
-
|
45
|
-
def initialize
|
46
|
-
@__result__ = {}
|
47
|
-
end
|
48
|
-
|
49
|
-
def attribute(name, **options)
|
50
|
-
name.is_a?(Symbol) or raise ArgumentError, "#{name.inspect} must be a Symbol"
|
51
|
-
|
52
|
-
spec = {}
|
53
|
-
spec[:default] = MapDefault[options] if options.key?(:default)
|
54
|
-
spec[:normalize] = MapNormalize[options] if options.key?(:normalize)
|
55
|
-
|
56
|
-
MapContract[options].then { spec[:contract] = _1 if _1 }
|
57
|
-
|
58
|
-
__result__[name] = spec
|
59
|
-
end
|
60
|
-
|
61
|
-
def contract
|
62
|
-
BCDD::Contract
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module BCDD
|
4
|
-
class Process
|
5
|
-
class OutputSpec
|
6
|
-
def initialize
|
7
|
-
@success = {}
|
8
|
-
@failure = {}
|
9
|
-
end
|
10
|
-
|
11
|
-
def Success(**spec)
|
12
|
-
@success = spec.transform_values(&BCDD::Contract)
|
13
|
-
end
|
14
|
-
|
15
|
-
def Failure(**spec)
|
16
|
-
@failure = spec.transform_values(&BCDD::Contract)
|
17
|
-
end
|
18
|
-
|
19
|
-
# :nodoc:
|
20
|
-
def __result__
|
21
|
-
{ success: @success, failure: @failure }
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def contract
|
27
|
-
::BCDD::Contract
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
File without changes
|
File without changes
|