ree_lib 1.0.36 → 1.0.38

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -2
  3. data/lib/ree_lib/Packages.schema.json +8 -0
  4. data/lib/ree_lib/packages/ree_actions/.gitignore +0 -0
  5. data/lib/ree_lib/packages/ree_actions/.rspec +2 -0
  6. data/lib/ree_lib/packages/ree_actions/Package.schema.json +20 -0
  7. data/lib/ree_lib/packages/ree_actions/bin/console +5 -0
  8. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action.rb +10 -0
  9. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_builder.rb +65 -0
  10. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_dsl.rb +60 -0
  11. data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +102 -0
  12. data/lib/ree_lib/packages/ree_actions/package/ree_actions.rb +12 -0
  13. data/lib/ree_lib/packages/ree_actions/spec/package_schema_spec.rb +14 -0
  14. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/action_dsl_spec.rb +62 -0
  15. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +93 -0
  16. data/lib/ree_lib/packages/ree_actions/spec/spec_helper.rb +3 -0
  17. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/functions/build_mapper_factory.rb +4 -0
  18. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +17 -10
  19. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +73 -35
  20. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +23 -0
  21. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/abstract_wrapper.rb +8 -0
  22. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/{types → wrappers}/array.rb +10 -17
  23. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +5 -1
  24. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +62 -2
  25. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/any_spec.rb +47 -0
  26. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb +4 -4
  27. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/{types → wrappers}/array_spec.rb +7 -7
  28. data/lib/ree_lib/packages/ree_roda/.gitignore +0 -0
  29. data/lib/ree_lib/packages/ree_roda/.rspec +2 -0
  30. data/lib/ree_lib/packages/ree_roda/Package.schema.json +58 -0
  31. data/lib/ree_lib/packages/ree_roda/bin/console +5 -0
  32. data/lib/ree_lib/packages/ree_roda/package/ree_roda/app.rb +46 -0
  33. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_actions.rb +150 -0
  34. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_logger.rb +66 -0
  35. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_action_errors.rb +76 -0
  36. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb +55 -0
  37. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/status_from_error.rb +25 -0
  38. data/lib/ree_lib/packages/ree_roda/package/ree_roda.rb +19 -0
  39. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json +28 -0
  40. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json +63 -0
  41. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json +28 -0
  42. data/lib/ree_lib/packages/ree_roda/spec/package_schema_spec.rb +14 -0
  43. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +84 -0
  44. data/lib/ree_lib/packages/ree_roda/spec/spec_helper.rb +3 -0
  45. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/beans/type_definitions_repo.rb +1 -1
  46. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_parameters_spec.rb +1 -1
  47. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_serializer_schema_spec.rb +3 -3
  48. data/lib/ree_lib/version.rb +1 -1
  49. metadata +65 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  class ReeMapper::MapperFactory
4
4
  class << self
5
- attr_reader :types, :strategies
5
+ attr_reader :types, :strategies, :wrappers
6
6
  end
7
7
 
8
8
  contract(Symbol => Nilor[ReeMapper::MapperStrategy])
@@ -18,9 +18,9 @@ class ReeMapper::MapperFactory
18
18
  )
19
19
  end
20
20
 
21
- contract(Symbol, ReeMapper::Mapper => Class).throws(ArgumentError)
21
+ contract(Symbol, ReeMapper::Mapper => SubclassOf[self]).throws(ArgumentError)
22
22
  def self.register_mapper(name, type)
23
- raise ArgumentError, "name of mapper type should not end with `?`" if name.to_s.end_with?('?')
23
+ raise ArgumentError, "mapper registration name should not end with `?`" if name.to_s.end_with?('?')
24
24
 
25
25
  defined_strategy_method = types[name]&.flat_map(&:strategy_methods)&.detect { type.find_strategy(_1) }
26
26
  raise ArgumentError, "type :#{name} with `#{defined_strategy_method}` strategy already registered" if defined_strategy_method
@@ -35,7 +35,7 @@ class ReeMapper::MapperFactory
35
35
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
36
36
  def #{name}(field_name = nil, optional: false, **opts)
37
37
  raise ReeMapper::Error, "invalid DSL usage" unless @mapper
38
- raise ArgumentError, "array item can't be optional" if field_name.nil? && optional
38
+ raise ArgumentError, "wrapped item can't be optional" if field_name.nil? && optional
39
39
 
40
40
  type = self.class.types.fetch(:#{name}).detect { (@mapper.strategy_methods - _1.strategy_methods).empty? }
41
41
 
@@ -43,9 +43,11 @@ class ReeMapper::MapperFactory
43
43
  raise ReeMapper::UnsupportedTypeError, "type :#{name} should implement `\#{@mapper.strategy_methods.join(', ')}`"
44
44
  end
45
45
 
46
- return ReeMapper::Field.new(type, optional: optional, **opts) unless field_name
46
+ field = ReeMapper::Field.new(type, field_name, optional: optional, **opts)
47
47
 
48
- @mapper.add_field(type, field_name, optional: optional, **opts)
48
+ return field unless field_name
49
+
50
+ @mapper.add_field(field)
49
51
  end
50
52
 
51
53
  def #{name}?(field_name, **opts)
@@ -56,6 +58,68 @@ class ReeMapper::MapperFactory
56
58
  self
57
59
  end
58
60
 
61
+ contract(Symbol, SubclassOf[ReeMapper::AbstractWrapper] => SubclassOf[self])
62
+ def self.register_wrapper(name, wrapper)
63
+ raise ArgumentError, "wrapper registration name should not end with `?`" if name.to_s.end_with?('?')
64
+ raise ArgumentError, "method :#{name} already defined" if !wrappers.key?(name) && method_defined?(name)
65
+
66
+ wrappers[name] ||= []
67
+ wrappers[name] << wrapper
68
+
69
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
70
+ contract(
71
+ Nilor[Symbol, ReeMapper::Field],
72
+ Nilor[ReeMapper::Field],
73
+ Kwargs[optional: Bool, dto: Nilor[Class]],
74
+ Ksplat[RestKeys => Any],
75
+ Optblock => Nilor[ReeMapper::Field]
76
+ ).throws(ReeMapper::Error, ArgumentError, ReeMapper::UnsupportedTypeError)
77
+ def #{name}(field_name = nil, subject = nil, optional: false, dto: nil, **opts, &blk)
78
+ raise ReeMapper::Error, "invalid DSL usage" unless @mapper
79
+ raise ArgumentError, 'wrapped type does not permit :dto without :block' if dto && !blk
80
+
81
+ if field_name.is_a?(ReeMapper::Field)
82
+ raise ArgumentError, "field_name should be a Symbol" if subject
83
+
84
+ subject = field_name
85
+ field_name = nil
86
+ end
87
+
88
+ raise ArgumentError, "wrapped item can't be optional" if field_name.nil? && optional
89
+ raise ArgumentError, "wrapped type should use either :subject or :block" if subject && blk || !subject && !blk
90
+
91
+ if blk
92
+ subject = ReeMapper::Field.new(
93
+ hash_from_blk(dto: dto, &blk)
94
+ )
95
+ end
96
+
97
+ wrapper = self.class.wrappers.fetch(:#{name}).detect do |wrapper|
98
+ @mapper.strategy_methods.all? { wrapper.method_defined?(_1) }
99
+ end
100
+
101
+ unless wrapper
102
+ raise ReeMapper::UnsupportedTypeError, "wrapper :#{name} should implement `\#{@mapper.strategy_methods.join(', ')}`"
103
+ end
104
+
105
+ type = ReeMapper::Mapper.build(@mapper.strategies, wrapper.new(subject))
106
+ type.name = :#{name}
107
+
108
+ field = ReeMapper::Field.new(type, field_name, optional: optional, **opts)
109
+
110
+ return field unless field_name
111
+
112
+ @mapper.add_field(field)
113
+ end
114
+
115
+ def #{name}?(*args, **opts, &blk)
116
+ #{name}(*args, optional: true, **opts, &blk)
117
+ end
118
+ RUBY
119
+
120
+ self
121
+ end
122
+
59
123
  contract(
60
124
  Kwargs[
61
125
  register_as: Nilor[Symbol]
@@ -71,41 +135,15 @@ class ReeMapper::MapperFactory
71
135
  @mapper = mapper
72
136
  end
73
137
 
74
- contract(Nilor[Symbol], Kwargs[each: Nilor[ReeMapper::Field], optional: Bool, dto: Nilor[Class]], Ksplat[RestKeys => Any], Optblock => Nilor[ReeMapper::Field])
75
- def array(field_name = nil, each: nil, optional: false, dto: nil, **opts, &blk)
76
- raise ReeMapper::Error, "invalid DSL usage" unless @mapper
77
- raise ArgumentError, "array item can't be optional" if field_name.nil? && optional
78
- raise ArgumentError, 'array type should use either :each or :block' if each && blk || !each && !blk
79
- raise ArgumentError, 'array does not permit :dto without :block' if dto && !blk
80
- raise ArgumentError, 'array does not permit :only and :except keys' if opts.key?(:only) || opts.key?(:except)
81
-
82
- if blk
83
- each = ReeMapper::Field.new(
84
- hash_from_blk(dto: dto, &blk)
85
- )
86
- end
87
-
88
- type = ReeMapper::Mapper.build(@mapper.strategies, ReeMapper::Array.new(each))
89
-
90
- return ReeMapper::Field.new(type, optional: optional, **opts) unless field_name
91
-
92
- @mapper.add_field(type, field_name, optional: optional, **opts)
93
- end
94
-
95
- contract(Symbol, Kwargs[each: Nilor[ReeMapper::Field]], Ksplat[RestKeys => Any], Optblock => Nilor[ReeMapper::Field])
96
- def array?(field_name, each: nil, **opts, &blk)
97
- raise ArgumentError if opts.key?(:optional)
98
-
99
- array(field_name, each: each, optional: true, **opts, &blk)
100
- end
101
-
102
138
  contract(Symbol, Kwargs[dto: Nilor[Class]], Ksplat[RestKeys => Any], Block => nil)
103
139
  def hash(field_name, dto: nil, **opts, &blk)
104
140
  raise ReeMapper::Error, "invalid DSL usage" unless @mapper
105
141
 
106
142
  type = hash_from_blk(dto: dto, &blk)
107
143
 
108
- @mapper.add_field(type, field_name, **opts)
144
+ field = ReeMapper::Field.new(type, field_name, **opts)
145
+
146
+ @mapper.add_field(field)
109
147
  end
110
148
 
111
149
  contract(Symbol, Ksplat[RestKeys => Any], Block => nil)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ReeMapper::Any < ReeMapper::AbstractType
4
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
5
+ def serialize(value, name:, role: nil)
6
+ value
7
+ end
8
+
9
+ contract(Any , Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
10
+ def cast(value, name:, role: nil)
11
+ value
12
+ end
13
+
14
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
15
+ def db_dump(value, name:, role: nil)
16
+ value
17
+ end
18
+
19
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
20
+ def db_load(value, name:, role: nil)
21
+ value
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ class ReeMapper::AbstractWrapper
2
+ attr_reader :subject
3
+
4
+ contract ReeMapper::Field => Any
5
+ def initialize(field)
6
+ @subject = field
7
+ end
8
+ end
@@ -1,22 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class ReeMapper::Array < ReeMapper::AbstractType
4
- attr_reader :of
5
-
6
- contract ReeMapper::Field => Any
7
- def initialize(of)
8
- @of = of
9
- end
10
-
3
+ class ReeMapper::Array < ReeMapper::AbstractWrapper
11
4
  contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]], fields_filters: ArrayOf[ReeMapper::FieldsFilter]] => Array)
12
5
  .throws(ReeMapper::TypeError)
13
6
  def serialize(value, name:, role: nil, fields_filters: [])
14
7
  if value.is_a?(Array)
15
8
  value.map.with_index {
16
- if _1.nil? && of.null
9
+ if _1.nil? && subject.null
17
10
  _1
18
11
  else
19
- of.type.serialize(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [of.fields_filter])
12
+ subject.type.serialize(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
20
13
  end
21
14
  }
22
15
  else
@@ -29,10 +22,10 @@ class ReeMapper::Array < ReeMapper::AbstractType
29
22
  def cast(value, name:, role: nil, fields_filters: [])
30
23
  if value.is_a?(Array)
31
24
  value.map.with_index {
32
- if _1.nil? && of.null
25
+ if _1.nil? && subject.null
33
26
  _1
34
27
  else
35
- of.type.cast(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [of.fields_filter])
28
+ subject.type.cast(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
36
29
  end
37
30
  }
38
31
  else
@@ -45,10 +38,10 @@ class ReeMapper::Array < ReeMapper::AbstractType
45
38
  def db_dump(value, name:, role: nil, fields_filters: [])
46
39
  if value.is_a?(Array)
47
40
  value.map.with_index {
48
- if _1.nil? && of.null
41
+ if _1.nil? && subject.null
49
42
  _1
50
43
  else
51
- of.type.db_dump(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [of.fields_filter])
44
+ subject.type.db_dump(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
52
45
  end
53
46
  }
54
47
  else
@@ -61,14 +54,14 @@ class ReeMapper::Array < ReeMapper::AbstractType
61
54
  def db_load(value, name:, role: nil, fields_filters: [])
62
55
  if value.is_a?(Array)
63
56
  value.map.with_index {
64
- if _1.nil? && of.null
57
+ if _1.nil? && subject.null
65
58
  _1
66
59
  else
67
- of.type.db_load(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [of.fields_filter])
60
+ subject.type.db_load(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
68
61
  end
69
62
  }
70
63
  else
71
64
  raise ReeMapper::TypeError, "`#{name}` should be an array"
72
65
  end
73
66
  end
74
- end
67
+ end
@@ -22,14 +22,18 @@ module ReeMapper
22
22
  require_relative 'ree_mapper/fields_filter'
23
23
  require_relative 'ree_mapper/field'
24
24
 
25
+
26
+ require_relative 'ree_mapper/wrappers/abstract_wrapper'
27
+ require_relative 'ree_mapper/wrappers/array'
28
+
25
29
  require_relative 'ree_mapper/types/bool'
30
+ require_relative 'ree_mapper/types/any'
26
31
  require_relative 'ree_mapper/types/date_time'
27
32
  require_relative 'ree_mapper/types/time'
28
33
  require_relative 'ree_mapper/types/date'
29
34
  require_relative 'ree_mapper/types/float'
30
35
  require_relative 'ree_mapper/types/integer'
31
36
  require_relative 'ree_mapper/types/string'
32
- require_relative 'ree_mapper/types/array'
33
37
 
34
38
  require_relative 'ree_mapper/strategy_outputs/strategy_output'
35
39
  require_relative 'ree_mapper/strategy_outputs/object_output'
@@ -43,7 +43,7 @@ RSpec.describe ReeMapper::MapperFactory do
43
43
  ).to eq({ val: { id: 1 } })
44
44
  }
45
45
 
46
- it 'allow to register caster and serializer with same name' do
46
+ it 'allow to register caster and serializer with the same name' do
47
47
  caster = mapper_factory.call.use(:cast) { string :name }
48
48
 
49
49
  mapper_factory.register_mapper(:new_type, serializer)
@@ -69,7 +69,7 @@ RSpec.describe ReeMapper::MapperFactory do
69
69
  it 'raise an error if the mapper name is ended by ?' do
70
70
  expect {
71
71
  mapper_factory.register_mapper(:new_type?, serializer)
72
- }.to raise_error(ArgumentError, 'name of mapper type should not end with `?`')
72
+ }.to raise_error(ArgumentError, 'mapper registration name should not end with `?`')
73
73
  end
74
74
 
75
75
  it 'raise an error if the mapper name is reserved' do
@@ -79,6 +79,66 @@ RSpec.describe ReeMapper::MapperFactory do
79
79
  end
80
80
  end
81
81
 
82
+ describe '.register_wrapper' do
83
+ let(:round_wrapper) {
84
+ Class.new(ReeMapper::AbstractWrapper) do
85
+ def serialize(value, name:, **opts)
86
+ raise ReeMapper::TypeError, "`#{name}` should be a number" if !value.is_a?(Numeric)
87
+
88
+ subject.type.serialize(value.round, name: name, **opts)
89
+ end
90
+ end
91
+ }
92
+
93
+ it {
94
+ mapper_factory.register_wrapper(:round, round_wrapper)
95
+
96
+ expect(
97
+ mapper_factory.call.use(:serialize) { round :val, integer }.serialize({ val: 1.1 })
98
+ ).to eq({ val: 1 })
99
+ }
100
+
101
+ it 'allow to register caster and serializer with the same name' do
102
+ caster_round_wrapper = Class.new(ReeMapper::AbstractWrapper) do
103
+ def cast(value, name:, **opts)
104
+ value = subject.type.cast(value, name: name, **opts)
105
+
106
+ raise ReeMapper::TypeError, "`#{name}` should be a number" if !value.is_a?(Numeric)
107
+ value.round
108
+ end
109
+ end
110
+
111
+ mapper_factory.register_wrapper(:round, round_wrapper)
112
+ mapper_factory.register_wrapper(:round, caster_round_wrapper)
113
+
114
+ expect(
115
+ mapper_factory.call.use(:serialize) { round :val, integer }.serialize({ val: 1.1 })
116
+ ).to eq({ val: 1 })
117
+
118
+ expect(
119
+ mapper_factory.call.use(:cast) { round :val, float }.cast({ val: '1.1' })
120
+ ).to eq({ val: 1 })
121
+ end
122
+
123
+ it 'raise an error if the registration wrapper name is ended by ?' do
124
+ expect {
125
+ mapper_factory.register_wrapper(:new_type?, round_wrapper)
126
+ }.to raise_error(ArgumentError, 'wrapper registration name should not end with `?`')
127
+ end
128
+
129
+ it 'raise an error if name is reserved' do
130
+ expect {
131
+ mapper_factory.register_wrapper(:hash, round_wrapper)
132
+ }.to raise_error(ArgumentError, 'method :hash already defined')
133
+ end
134
+
135
+ it 'raise an error if name is reserved by mapper' do
136
+ expect {
137
+ mapper_factory.register_wrapper(:integer, round_wrapper)
138
+ }.to raise_error(ArgumentError, 'method :integer already defined')
139
+ end
140
+ end
141
+
82
142
  describe '.use' do
83
143
  it {
84
144
  mapper = mapper_factory.call.use(:cast) do
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'ReeMapper::Bool' do
4
+ link :build_mapper_factory, from: :ree_mapper
5
+ link :build_mapper_strategy, from: :ree_mapper
6
+
7
+ let(:mapper_factory) {
8
+ build_mapper_factory(
9
+ strategies: [
10
+ build_mapper_strategy(method: :cast, dto: Hash),
11
+ build_mapper_strategy(method: :serialize, dto: Hash),
12
+ build_mapper_strategy(method: :db_dump, dto: Hash),
13
+ build_mapper_strategy(method: :db_load, dto: Hash)
14
+ ]
15
+ )
16
+ }
17
+
18
+ let(:mapper) {
19
+ mapper_factory.call.use(:cast).use(:serialize).use(:db_dump).use(:db_load) {
20
+ any :any
21
+ }
22
+ }
23
+
24
+ describe '#serialize' do
25
+ it {
26
+ expect(mapper.serialize({ any: true })).to eq({ any: true })
27
+ }
28
+ end
29
+
30
+ describe '#cast' do
31
+ it {
32
+ expect(mapper.cast({ 'any' => true })).to eq({ any: true })
33
+ }
34
+ end
35
+
36
+ describe '#db_dump' do
37
+ it {
38
+ expect(mapper.db_dump(OpenStruct.new({ any: true }))).to eq({ any: true })
39
+ }
40
+ end
41
+
42
+ describe '#db_load' do
43
+ it {
44
+ expect(mapper.db_load({ 'any' => true })).to eq({ any: true })
45
+ }
46
+ end
47
+ end
@@ -21,7 +21,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
21
21
  integer :x
22
22
  integer :y
23
23
  integer :z
24
- }
24
+ }
25
25
  }
26
26
 
27
27
  context 'with only' do
@@ -71,7 +71,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
71
71
  point :y, except: [:x, :z]
72
72
  end
73
73
 
74
- array :points, each: point(only: [:x, :y])
74
+ array :points, point(only: [:x, :y])
75
75
  }
76
76
  }
77
77
 
@@ -169,7 +169,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
169
169
  integer :number
170
170
  integer? :opt_number
171
171
  integer :opt_number_long, optional: true
172
- array? :opt_array, each: integer
172
+ array? :opt_array, integer
173
173
  array? :opt_array_with_blk do
174
174
  integer :id
175
175
  end
@@ -278,7 +278,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
278
278
  integer :for_all
279
279
  integer :for_admin, role: :admin
280
280
  }
281
-
281
+
282
282
  mapper_factory.call.use(:cast) {
283
283
  nested_type :my_field
284
284
  }
@@ -17,8 +17,8 @@ RSpec.describe 'ReeMapper::Array' do
17
17
 
18
18
  let(:mapper) {
19
19
  mapper_factory.call.use(:cast).use(:serialize).use(:db_dump).use(:db_load) {
20
- array :tags, each: integer
21
- array? :ary_of_ary, each: array(each: integer)
20
+ array :tags, integer
21
+ array? :ary_of_ary, array(integer)
22
22
  }
23
23
  }
24
24
 
@@ -73,7 +73,7 @@ RSpec.describe 'ReeMapper::Array' do
73
73
  context 'with array of array' do
74
74
  let(:mapper) {
75
75
  mapper_factory.call.use(:serialize) {
76
- array :coords, each: array(each: integer)
76
+ array :coords, array(integer)
77
77
  }
78
78
  }
79
79
 
@@ -85,7 +85,7 @@ RSpec.describe 'ReeMapper::Array' do
85
85
  context 'with nullable element of array' do
86
86
  let(:mapper) {
87
87
  mapper_factory.call.use(:serialize) {
88
- array :tags, each: integer(null: true)
88
+ array :tags, integer(null: true)
89
89
  }
90
90
  }
91
91
 
@@ -98,7 +98,7 @@ RSpec.describe 'ReeMapper::Array' do
98
98
  it {
99
99
  expect {
100
100
  mapper_factory.call.use(:serialize) {
101
- array :tags, each: integer?
101
+ array :tags, integer?
102
102
  }
103
103
  }.to raise_error(ArgumentError)
104
104
  }
@@ -106,7 +106,7 @@ RSpec.describe 'ReeMapper::Array' do
106
106
  it {
107
107
  expect {
108
108
  mapper_factory.call.use(:serialize) {
109
- array :tags, each: integer(optional: true)
109
+ array :tags, integer(optional: true)
110
110
  }
111
111
  }.to raise_error(ArgumentError)
112
112
  }
@@ -114,7 +114,7 @@ RSpec.describe 'ReeMapper::Array' do
114
114
  it {
115
115
  expect {
116
116
  mapper_factory.call.use(:serialize) {
117
- array :tags, each: array(each: integer, optional: true)
117
+ array :tags, array(integer, optional: true)
118
118
  }
119
119
  }.to raise_error(ArgumentError)
120
120
  }
File without changes
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,58 @@
1
+ {
2
+ "schema_type": "package",
3
+ "schema_version": "1.1",
4
+ "name": "ree_roda",
5
+ "entry_path": "packages/ree_roda/package/ree_roda.rb",
6
+ "tags": [
7
+ "ree_roda"
8
+ ],
9
+ "depends_on": [
10
+ {
11
+ "name": "ree_actions"
12
+ },
13
+ {
14
+ "name": "ree_errors"
15
+ },
16
+ {
17
+ "name": "ree_hash"
18
+ },
19
+ {
20
+ "name": "ree_json"
21
+ },
22
+ {
23
+ "name": "ree_logger"
24
+ },
25
+ {
26
+ "name": "ree_object"
27
+ },
28
+ {
29
+ "name": "ree_swagger"
30
+ }
31
+ ],
32
+ "env_vars": [
33
+
34
+ ],
35
+ "objects": [
36
+ {
37
+ "name": "build_action_errors",
38
+ "schema": "packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json",
39
+ "tags": [
40
+ "fn"
41
+ ]
42
+ },
43
+ {
44
+ "name": "build_swagger_from_actions",
45
+ "schema": "packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json",
46
+ "tags": [
47
+ "fn"
48
+ ]
49
+ },
50
+ {
51
+ "name": "status_from_error",
52
+ "schema": "packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json",
53
+ "tags": [
54
+ "fn"
55
+ ]
56
+ }
57
+ ]
58
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "ree"
4
+
5
+ Ree.init(__dir__, irb: true)
@@ -0,0 +1,46 @@
1
+ package_require("ree_errors/error")
2
+ package_require("ree_mapper/errors/type_error")
3
+
4
+ class ReeRoda::App < Roda
5
+ include Ree::LinkDSL
6
+
7
+ link :logger, from: :ree_logger
8
+ link :status_from_error
9
+ link :to_json, from: :ree_json
10
+
11
+ plugin :error_handler
12
+ plugin :json_parser
13
+ plugin :type_routing, default_type: :json
14
+
15
+ error do |e|
16
+ response["Content-Type"] = "application/json"
17
+
18
+ if e.is_a?(ReeErrors::Error)
19
+ body = {
20
+ code: e.code,
21
+ message: e.message,
22
+ type: e.type,
23
+ }
24
+
25
+ response.status = status_from_error(e.type)
26
+ response.write(to_json(body))
27
+ response.finish
28
+ elsif e.is_a?(ReeMapper::TypeError) || e.is_a?(ReeMapper::CoercionError)
29
+ body = {
30
+ code: "param",
31
+ message: e.message,
32
+ type: :invalid_param,
33
+ }
34
+
35
+ response.status = 400
36
+ response.write(to_json(body))
37
+ response.finish
38
+ else
39
+ logger.error(e.message, {}, e)
40
+ response["Content-Type"] = "text/plain"
41
+ response.status = 500
42
+ response.write("unhandled server error")
43
+ response.finish
44
+ end
45
+ end
46
+ end