remap 2.0.2 → 2.1.5
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/lib/remap/base.rb +229 -75
- data/lib/remap/compiler.rb +403 -37
- data/lib/remap/constructor/argument.rb +20 -6
- data/lib/remap/constructor/keyword.rb +20 -4
- data/lib/remap/constructor/none.rb +3 -4
- data/lib/remap/constructor.rb +12 -5
- data/lib/remap/contract.rb +27 -0
- data/lib/remap/extensions/enumerable.rb +48 -0
- data/lib/remap/extensions/hash.rb +13 -0
- data/lib/remap/extensions/object.rb +37 -0
- data/lib/remap/failure.rb +25 -15
- data/lib/remap/iteration/array.rb +20 -11
- data/lib/remap/iteration/hash.rb +21 -13
- data/lib/remap/iteration/other.rb +7 -7
- data/lib/remap/iteration.rb +8 -2
- data/lib/remap/mapper/and.rb +29 -7
- data/lib/remap/mapper/binary.rb +3 -6
- data/lib/remap/mapper/or.rb +29 -6
- data/lib/remap/mapper/support/operations.rb +40 -0
- data/lib/remap/mapper/xor.rb +29 -7
- data/lib/remap/mapper.rb +1 -48
- data/lib/remap/notice/traced.rb +19 -0
- data/lib/remap/notice/untraced.rb +11 -0
- data/lib/remap/notice.rb +34 -0
- data/lib/remap/operation.rb +26 -13
- data/lib/remap/path/input.rb +37 -0
- data/lib/remap/path/output.rb +26 -0
- data/lib/remap/path.rb +22 -0
- data/lib/remap/path_error.rb +13 -0
- data/lib/remap/proxy.rb +18 -0
- data/lib/remap/rule/each.rb +25 -24
- data/lib/remap/rule/embed.rb +33 -28
- data/lib/remap/rule/map/optional.rb +42 -0
- data/lib/remap/rule/map/required.rb +35 -0
- data/lib/remap/rule/map.rb +176 -55
- data/lib/remap/rule/set.rb +23 -33
- data/lib/remap/rule/support/collection/empty.rb +7 -7
- data/lib/remap/rule/support/collection/filled.rb +21 -8
- data/lib/remap/rule/support/collection.rb +11 -3
- data/lib/remap/rule/support/enum.rb +44 -21
- data/lib/remap/rule/void.rb +17 -18
- data/lib/remap/rule/wrap.rb +25 -17
- data/lib/remap/rule.rb +8 -1
- data/lib/remap/selector/all.rb +29 -7
- data/lib/remap/selector/index.rb +24 -16
- data/lib/remap/selector/key.rb +31 -16
- data/lib/remap/selector.rb +17 -0
- data/lib/remap/state/extension.rb +182 -208
- data/lib/remap/state/schema.rb +1 -1
- data/lib/remap/state.rb +30 -4
- data/lib/remap/static/fixed.rb +14 -3
- data/lib/remap/static/option.rb +21 -6
- data/lib/remap/static.rb +13 -0
- data/lib/remap/struct.rb +1 -0
- data/lib/remap/types.rb +13 -28
- data/lib/remap.rb +15 -19
- metadata +95 -93
- data/lib/remap/result.rb +0 -11
- data/lib/remap/rule/support/path.rb +0 -45
- data/lib/remap/state/types.rb +0 -11
- data/lib/remap/success.rb +0 -29
- data/lib/remap/version.rb +0 -5
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
class Contract < Dry::Validation::Contract
|
5
|
+
# Constructs a contract used to validate mapper input
|
6
|
+
#
|
7
|
+
# @param rules [Array<Proc>]
|
8
|
+
# @param options [Hash]
|
9
|
+
# @param contract [Proc]
|
10
|
+
# @param attributes [Hash]
|
11
|
+
#
|
12
|
+
# @return [Contract]
|
13
|
+
def self.call(rules:, options:, contract:, attributes:)
|
14
|
+
Class.new(self) do
|
15
|
+
rules.each do |rule|
|
16
|
+
class_eval(&rule)
|
17
|
+
end
|
18
|
+
|
19
|
+
options.each do |option|
|
20
|
+
class_eval(&option)
|
21
|
+
end
|
22
|
+
|
23
|
+
schema(contract)
|
24
|
+
end.new(**attributes)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
module Extensions
|
5
|
+
using Object
|
6
|
+
|
7
|
+
module Enumerable
|
8
|
+
refine ::Enumerable do
|
9
|
+
# Creates a hash using {self} as the {path} and {value} as the hash value
|
10
|
+
#
|
11
|
+
# @param value [Any] Hash value
|
12
|
+
#
|
13
|
+
# @example A hash from path
|
14
|
+
# [:a, :b].hide('value') # => { a: { b: 'value' } }
|
15
|
+
#
|
16
|
+
# @return [Hash]
|
17
|
+
def hide(value)
|
18
|
+
reverse.reduce(value) do |element, key|
|
19
|
+
{ key => element }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Fetches value at {path}
|
24
|
+
#
|
25
|
+
# @example Fetch value at path
|
26
|
+
# [[:a, :b], [:c, :d]].get(0, 1) # => :b
|
27
|
+
#
|
28
|
+
# @return [Any]
|
29
|
+
#
|
30
|
+
# @raise When path cannot be found
|
31
|
+
def get(*path, &error)
|
32
|
+
_, result = path.reduce([
|
33
|
+
EMPTY_ARRAY,
|
34
|
+
self
|
35
|
+
]) do |(current_path, element), key|
|
36
|
+
value = element.fetch(key) do
|
37
|
+
raise PathError, current_path + [key]
|
38
|
+
end
|
39
|
+
|
40
|
+
[current_path + [key], value]
|
41
|
+
end
|
42
|
+
|
43
|
+
result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
module Extensions
|
5
|
+
module Object
|
6
|
+
refine ::Object do
|
7
|
+
# Fallback validation method
|
8
|
+
#
|
9
|
+
# @yield if block is provided
|
10
|
+
#
|
11
|
+
# @raise unless block is provided
|
12
|
+
def _(&block)
|
13
|
+
unless block
|
14
|
+
return _ { raise _1 }
|
15
|
+
end
|
16
|
+
|
17
|
+
block["Expected a state, got [#{self}] (#{self.class})"]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Fallback method used when #get is called on an object that does not respond to #get
|
21
|
+
#
|
22
|
+
# Block is invoked, if provided
|
23
|
+
# Otherwise a symbol is thrown
|
24
|
+
#
|
25
|
+
# @param path [Array<Key>]
|
26
|
+
def get(*path, &block)
|
27
|
+
raise PathError, []
|
28
|
+
end
|
29
|
+
alias_method :fetch, :get
|
30
|
+
|
31
|
+
def formated
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/remap/failure.rb
CHANGED
@@ -1,27 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Remap
|
4
|
-
|
5
|
-
attribute :reasons, Types::Hash
|
4
|
+
using Extensions::Hash
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
class Failure < Dry::Concrete
|
7
|
+
attribute :failures, [Notice], min_size: 1
|
8
|
+
attribute? :notices, [Notice], default: EMPTY_ARRAY
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
# Merges two failures
|
11
|
+
#
|
12
|
+
# @param other [Failure]
|
13
|
+
#
|
14
|
+
# @return [Failure]
|
15
|
+
def merge(other)
|
16
|
+
unless other.is_a?(self.class)
|
17
|
+
raise ArgumentError, "can't merge #{self.class} with #{other.class}"
|
18
|
+
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
failure = attributes.deep_merge(other.attributes) do |_, value1, value2|
|
21
|
+
case [value1, value2]
|
22
|
+
in [Array, Array]
|
23
|
+
value1 + value2
|
24
|
+
else
|
25
|
+
raise ArgumentError, "can't merge #{self.class} with #{other.class}"
|
26
|
+
end
|
27
|
+
end
|
18
28
|
|
19
|
-
|
20
|
-
false
|
29
|
+
new(failure)
|
21
30
|
end
|
22
31
|
|
23
|
-
|
24
|
-
|
32
|
+
# @return [String]
|
33
|
+
def exception
|
34
|
+
Error.new(attributes.formated)
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -2,28 +2,37 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Iteration
|
5
|
+
using State::Extension
|
6
|
+
|
7
|
+
# Implements an array iterator which defines index in state
|
5
8
|
class Array < Concrete
|
6
|
-
|
9
|
+
# @return [Array<T>]
|
10
|
+
attribute :value, Types::Array, alias: :array
|
7
11
|
|
8
|
-
|
12
|
+
# @return [State<Array<T>>]
|
9
13
|
attribute :state, Types::State
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
input_state.merged(new_array_state)
|
17
|
-
end
|
18
|
-
end._
|
15
|
+
# @see Iteration#map
|
16
|
+
def call(&block)
|
17
|
+
array.each_with_index.reduce(init) do |state, (value, index)|
|
18
|
+
reduce(state, value, index, &block)
|
19
|
+
end
|
19
20
|
end
|
20
|
-
alias call map
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def init
|
25
25
|
state.set(EMPTY_ARRAY)
|
26
26
|
end
|
27
|
+
|
28
|
+
def reduce(state, value, index, &block)
|
29
|
+
notice = catch :ignore do
|
30
|
+
other = block[value, index: index]
|
31
|
+
return state.combine(other.fmap { [_1] })
|
32
|
+
end
|
33
|
+
|
34
|
+
state.set(notice: notice)
|
35
|
+
end
|
27
36
|
end
|
28
37
|
end
|
29
38
|
end
|
data/lib/remap/iteration/hash.rb
CHANGED
@@ -2,26 +2,34 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Iteration
|
5
|
+
using State::Extension
|
6
|
+
|
7
|
+
# Implements a hash iterator which defines key in state
|
5
8
|
class Hash < Concrete
|
6
|
-
|
9
|
+
# @return [Hash]
|
10
|
+
attribute :value, Types::Hash, alias: :hash
|
11
|
+
|
12
|
+
# @return [State<Hash>]
|
7
13
|
attribute :state, Types::State
|
8
14
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
block[value, key: key]._.then do |new_state|
|
15
|
-
new_state.fmap { { key => _1 } }
|
16
|
-
end.then do |new_hash_state|
|
17
|
-
input_state.merged(new_hash_state)
|
18
|
-
end
|
19
|
-
end._
|
15
|
+
# @see Iteration#map
|
16
|
+
def call(&block)
|
17
|
+
hash.reduce(init) do |state, (key, value)|
|
18
|
+
reduce(state, key, value, &block)
|
19
|
+
end
|
20
20
|
end
|
21
|
-
alias call map
|
22
21
|
|
23
22
|
private
|
24
23
|
|
24
|
+
def reduce(state, key, value, &block)
|
25
|
+
notice = catch :ignore do
|
26
|
+
other = block[value, key: key]
|
27
|
+
return state.combine(other.fmap { { key => _1 } })
|
28
|
+
end
|
29
|
+
|
30
|
+
state.set(notice: notice)
|
31
|
+
end
|
32
|
+
|
25
33
|
def init
|
26
34
|
state.set(EMPTY_HASH)
|
27
35
|
end
|
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Iteration
|
5
|
+
using State::Extension
|
6
|
+
|
7
|
+
# Default iterator which doesn't do anything
|
5
8
|
class Other < Concrete
|
9
|
+
attribute :value, Types::Any, alias: :other
|
6
10
|
attribute :state, Types::State
|
7
|
-
attribute :value, Types::Any
|
8
|
-
|
9
|
-
using State::Extension
|
10
11
|
|
11
|
-
# @see
|
12
|
-
def
|
13
|
-
|
12
|
+
# @see Iteration#map
|
13
|
+
def call(&block)
|
14
|
+
state.fatal!("Expected an enumerable, got %s (%s)", value, value.class)
|
14
15
|
end
|
15
|
-
alias call map
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/remap/iteration.rb
CHANGED
@@ -2,10 +2,13 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Iteration < Dry::Interface
|
5
|
-
|
5
|
+
# @return [State<T>]
|
6
6
|
attribute :state, Types::State
|
7
7
|
|
8
|
-
#
|
8
|
+
# @return [T]
|
9
|
+
attribute :value, Types::Any
|
10
|
+
|
11
|
+
# Maps every element in {#value}
|
9
12
|
#
|
10
13
|
# @abstract
|
11
14
|
#
|
@@ -14,6 +17,9 @@ module Remap
|
|
14
17
|
# @yieldreturn [Array<V>, Hash<V, K>]
|
15
18
|
#
|
16
19
|
# @return [Array<V>, Hash<V, K>]
|
20
|
+
def call(state)
|
21
|
+
raise NotImplementedError, "#{self.class}#call not implemented"
|
22
|
+
end
|
17
23
|
|
18
24
|
order :Hash, :Array, :Other
|
19
25
|
end
|
data/lib/remap/mapper/and.rb
CHANGED
@@ -2,14 +2,36 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Mapper
|
5
|
-
|
6
|
-
using State::Extension
|
5
|
+
using State::Extension
|
7
6
|
|
7
|
+
# Represents two mappers that are combined with the & operator
|
8
|
+
#
|
9
|
+
# @example Combine two mappers
|
10
|
+
# class Mapper1 < Remap::Base
|
11
|
+
# contract do
|
12
|
+
# required(:a1)
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class Mapper2 < Remap::Base
|
17
|
+
# contract do
|
18
|
+
# required(:a2)
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# state = Remap::State.call({ a2: 2, a1: 1 })
|
23
|
+
# output = (Mapper1 & Mapper2).call!(state)
|
24
|
+
# output.fetch(:value) # => { a2: 2, a1: 1 }
|
25
|
+
class And < Binary
|
26
|
+
# Succeeds if both left and right succeed
|
27
|
+
# Returns the combined result of left and right
|
28
|
+
#
|
29
|
+
# @param state [State]
|
30
|
+
#
|
31
|
+
# @yield [Failure] if mapper fails
|
32
|
+
#
|
33
|
+
# @return [Result]
|
8
34
|
def call!(state, &error)
|
9
|
-
unless error
|
10
|
-
return call!(state, &exception)
|
11
|
-
end
|
12
|
-
|
13
35
|
state1 = left.call!(state) do |failure1|
|
14
36
|
right.call!(state) do |failure2|
|
15
37
|
return error[failure1.merge(failure2)]
|
@@ -22,7 +44,7 @@ module Remap
|
|
22
44
|
return error[failure]
|
23
45
|
end
|
24
46
|
|
25
|
-
state1.
|
47
|
+
state1.combine(state2)
|
26
48
|
end
|
27
49
|
end
|
28
50
|
end
|
data/lib/remap/mapper/binary.rb
CHANGED
@@ -2,15 +2,12 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Mapper
|
5
|
+
# @abstract
|
5
6
|
class Binary < self
|
7
|
+
include Operation
|
8
|
+
|
6
9
|
attribute :left, Types::Mapper
|
7
10
|
attribute :right, Types::Mapper
|
8
|
-
|
9
|
-
def exception
|
10
|
-
->(error) { raise error }
|
11
|
-
end
|
12
|
-
|
13
|
-
include Operation
|
14
11
|
end
|
15
12
|
end
|
16
13
|
end
|
data/lib/remap/mapper/or.rb
CHANGED
@@ -2,14 +2,37 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Mapper
|
5
|
-
|
6
|
-
using State::Extension
|
5
|
+
using State::Extension
|
7
6
|
|
7
|
+
# Represents two mappers that are combined with the | operator
|
8
|
+
#
|
9
|
+
# @example Combine two mappers
|
10
|
+
# class Mapper1 < Remap::Base
|
11
|
+
# contract do
|
12
|
+
# required(:a1)
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class Mapper2 < Remap::Base
|
17
|
+
# contract do
|
18
|
+
# required(:a2)
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# state = Remap::State.call({ a2: 2 })
|
23
|
+
# result = (Mapper1 | Mapper2).call!(state)
|
24
|
+
# result.fetch(:value) # => { a2: 2 }
|
25
|
+
class Or < Binary
|
26
|
+
# Succeeds if left or right succeeds
|
27
|
+
# Returns which ever succeeds first
|
28
|
+
#
|
29
|
+
# @param state [State]
|
30
|
+
#
|
31
|
+
# @yieldparam [Failure] if mapper fails
|
32
|
+
# @yieldreturn [Failure]
|
33
|
+
#
|
34
|
+
# @return [Result]
|
8
35
|
def call!(state, &error)
|
9
|
-
unless error
|
10
|
-
return call!(state, &exception)
|
11
|
-
end
|
12
|
-
|
13
36
|
left.call!(state) do |failure1|
|
14
37
|
return right.call!(state) do |failure2|
|
15
38
|
return error[failure1.merge(failure2)]
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
class Mapper
|
5
|
+
module Operations
|
6
|
+
# Tries self and other and returns the first successful result
|
7
|
+
#
|
8
|
+
# @param other [Mapper]
|
9
|
+
#
|
10
|
+
# @return [Mapper::Or]
|
11
|
+
def |(other)
|
12
|
+
Or.new(left: self, right: other)
|
13
|
+
rescue Dry::Struct::Error => e
|
14
|
+
raise ArgumentError, e.message
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a successful result when self & other are successful
|
18
|
+
#
|
19
|
+
# @param other [Mapper]
|
20
|
+
#
|
21
|
+
# @return [Mapper::And]
|
22
|
+
def &(other)
|
23
|
+
And.new(left: self, right: other)
|
24
|
+
rescue Dry::Struct::Error => e
|
25
|
+
raise ArgumentError, e.message
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a successful result when only one of self & other are successful
|
29
|
+
#
|
30
|
+
# @param other [Mapper]
|
31
|
+
#
|
32
|
+
# @return [Mapper:Xor]
|
33
|
+
def ^(other)
|
34
|
+
Xor.new(left: self, right: other)
|
35
|
+
rescue Dry::Struct::Error => e
|
36
|
+
raise ArgumentError, e.message
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/remap/mapper/xor.rb
CHANGED
@@ -2,14 +2,36 @@
|
|
2
2
|
|
3
3
|
module Remap
|
4
4
|
class Mapper
|
5
|
-
|
6
|
-
using State::Extension
|
5
|
+
using State::Extension
|
7
6
|
|
7
|
+
# Represents two mappers that are combined with the ^ operator
|
8
|
+
#
|
9
|
+
# @example Combine two mappers
|
10
|
+
# class Mapper1 < Remap::Base
|
11
|
+
# contract do
|
12
|
+
# required(:a1)
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class Mapper2 < Remap::Base
|
17
|
+
# contract do
|
18
|
+
# required(:a2)
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# state = Remap::State.call({ a2: 2 })
|
23
|
+
# output = (Mapper1 ^ Mapper2).call!(state)
|
24
|
+
# output.fetch(:value) # => { a2: 2 }
|
25
|
+
class Xor < Binary
|
26
|
+
# Succeeds if left or right succeeds, but not both
|
27
|
+
#
|
28
|
+
# @param state [State]
|
29
|
+
#
|
30
|
+
# @yieldparam [Failure] if mapper fails
|
31
|
+
# @yieldreturn [Failure]
|
32
|
+
#
|
33
|
+
# @return [Result]
|
8
34
|
def call!(state, &error)
|
9
|
-
unless error
|
10
|
-
return call!(state, &exception)
|
11
|
-
end
|
12
|
-
|
13
35
|
state1 = left.call!(state) do |failure1|
|
14
36
|
return right.call!(state) do |failure2|
|
15
37
|
return error[failure1.merge(failure2)]
|
@@ -20,7 +42,7 @@ module Remap
|
|
20
42
|
return state1
|
21
43
|
end
|
22
44
|
|
23
|
-
|
45
|
+
state1.combine(state2).failure("Both left and right passed xor operation").then(&error)
|
24
46
|
end
|
25
47
|
end
|
26
48
|
end
|
data/lib/remap/mapper.rb
CHANGED
@@ -3,54 +3,7 @@
|
|
3
3
|
module Remap
|
4
4
|
# @abstract
|
5
5
|
class Mapper < Struct
|
6
|
-
# Tries {self} and {other} and returns the first successful result
|
7
|
-
#
|
8
|
-
# @param other [Mapper]
|
9
|
-
#
|
10
|
-
# @return [Mapper::Or]
|
11
|
-
module Operations
|
12
|
-
def |(other)
|
13
|
-
Or.new(left: self, right: other)
|
14
|
-
rescue Dry::Struct::Error => e
|
15
|
-
raise ArgumentError, e.message
|
16
|
-
end
|
17
|
-
|
18
|
-
# Returns a successful result when {self} & {other} are successful
|
19
|
-
#
|
20
|
-
# @param other [Mapper]
|
21
|
-
#
|
22
|
-
# @return [Mapper::And]
|
23
|
-
def &(other)
|
24
|
-
And.new(left: self, right: other)
|
25
|
-
rescue Dry::Struct::Error => e
|
26
|
-
raise ArgumentError, e.message
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns a successful result when only one of {self} & {other} are successful
|
30
|
-
#
|
31
|
-
# @param other [Mapper]
|
32
|
-
#
|
33
|
-
# @return [Mapper:Xor]
|
34
|
-
def ^(other)
|
35
|
-
Xor.new(left: self, right: other)
|
36
|
-
rescue Dry::Struct::Error => e
|
37
|
-
raise ArgumentError, e.message
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
include Operations
|
42
6
|
extend Operations
|
43
|
-
|
44
|
-
# Creates a new mapper using {state}
|
45
|
-
#
|
46
|
-
# @param state [State]
|
47
|
-
#
|
48
|
-
# @yield [State]
|
49
|
-
# If the call fails, the block is invoked with the state
|
50
|
-
# @yieldreturn [State]
|
51
|
-
#
|
52
|
-
# @return [State]
|
53
|
-
#
|
54
|
-
# @private
|
7
|
+
include Operations
|
55
8
|
end
|
56
9
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
class Notice
|
5
|
+
class Traced < Concrete
|
6
|
+
attribute? :backtrace, Types::Backtrace, default: EMPTY_ARRAY
|
7
|
+
|
8
|
+
def traced(backtrace)
|
9
|
+
Notice.call(**attributes, backtrace: backtrace)
|
10
|
+
end
|
11
|
+
|
12
|
+
def exception
|
13
|
+
return super if backtrace.blank?
|
14
|
+
|
15
|
+
super.tap { _1.set_backtrace(backtrace.map(&:to_s)) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/remap/notice.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
using Extensions::Hash
|
5
|
+
|
6
|
+
class Notice < Dry::Interface
|
7
|
+
attribute? :value, Types::Any
|
8
|
+
attribute :reason, String
|
9
|
+
attribute :path, Array
|
10
|
+
|
11
|
+
class Error < Remap::Error
|
12
|
+
extend Dry::Initializer
|
13
|
+
|
14
|
+
param :notice, type: Notice
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect
|
18
|
+
"#<%s %s>" % [self.class, to_hash.formated]
|
19
|
+
end
|
20
|
+
alias to_s inspect
|
21
|
+
|
22
|
+
# Hash representation of the notice
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
def to_hash
|
26
|
+
super.except(:backtrace).compact_blank
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Error]
|
30
|
+
def exception
|
31
|
+
Error.new(self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|