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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b912c6dd7bbc76a3a091da0e5d722fea38b97ff0ac93f61a4477e20e8ba7d26
4
- data.tar.gz: c0161a5ccc0f6275b28187b822dd20dc9d35640b7461827bef8fcbe5beb9b491
3
+ metadata.gz: 60c6b5184edd4076e88382736efff9e0981be518c064ae290a75ad4d052d3196
4
+ data.tar.gz: ca15261b4991198f5277cddf5f2c2133458e7163f8388e39d5a0c18dad688bce
5
5
  SHA512:
6
- metadata.gz: cf2fd171d9beae0ba6d90f768fbd4c8966f4a2e2d54d7c7ec9d220b35f0f0ab420cfeb3d786f6749165480eb888dacae9ae1a2a521c0e7d284b859addf618e4e
7
- data.tar.gz: 65848285149f38f9d88114e8a1277e2b4f943237a056e7a519fb2fcaab4a7d17a47edaa0fdb351f4252d898ba56313ed27ad79401cb704be1f338589c53d863a
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, contract: :is_uuid, normalize: -> { _1.strip.downcase }, default: -> { ::SecureRandom.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, contract: :is_uuid, normalize: -> { _1.strip.downcase }, default: -> { ::SecureRandom.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
@@ -12,6 +12,7 @@ require 'db/setup'
12
12
  require 'lib/bcdd/result/rollback_on_failure'
13
13
  require 'lib/bcdd/result/transitions_record'
14
14
  require 'lib/bcdd/contracts'
15
+ require 'lib/bcdd/values/uuid'
15
16
  require 'lib/runtime_breaker'
16
17
 
17
18
  module TransitionsListener
@@ -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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BCDD
4
4
  class Process
5
- VERSION = '0.3.1'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
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 'contracts'
7
- require_relative 'contract/null'
5
+ require_relative 'ext/contract'
6
+ require_relative 'ext/data'
8
7
 
9
8
  require_relative 'process/version'
10
- require_relative 'process/caller'
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
- class << self
17
- attr_reader :__input__, :__input_contract__, :__output__
13
+ module Caller
14
+ def call(**kargs)
15
+ input = self.class::Input.new(**kargs)
18
16
 
19
- def input(&block)
20
- return @__input__ if defined?(@__input__)
17
+ Result.transitions(name: self.class.name) do
18
+ return Failure(:invalid_input, **input.errors) if input.errors.any?
21
19
 
22
- spec = InputSpec.new
23
- spec.instance_eval(&block)
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
- def output(expectations: true, &block)
31
- @__output__ and raise ArgumentError, 'outputs already defined'
25
+ def self.input(&block)
26
+ return if const_defined?(:Input)
32
27
 
33
- config = { addon: { given: true, continue: true } }
28
+ const_set(:Input, ::BCDD::Data.new(&block))
29
+ end
34
30
 
35
- if expectations
36
- spec = OutputSpec.new
37
- spec.instance_eval(&block)
31
+ RESULT_CONFIG = { addon: { given: true, continue: true }.freeze }.freeze
38
32
 
39
- output = spec.__result__
40
- success = output[:success]
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
- include(Result::Context::Expectations.mixin(config: config, success: success, failure: failure))
44
- else
45
- include(Result::Context.mixin(config: config))
46
- end
36
+ if expectations
37
+ evaluator = Output::Evaluator.new
38
+ evaluator.instance_eval(&block)
47
39
 
48
- @__output__ = { expectations: expectations }.freeze
49
- end
40
+ success = evaluator.__properties__.success
41
+ failure = evaluator.__properties__.failure
50
42
 
51
- def inherited(subclass)
52
- subclass.prepend(Caller)
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
- def call(**input)
56
- new.call(**input)
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.3.1
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-02 00:00:00.000000000 Z
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/null.rb
75
- - lib/bcdd/contracts.rb
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/caller.rb
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
@@ -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