bcdd-process 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|