salestation 3.5.1 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a23825882ed43419fc0dd8a70d9cc4cf0b24b318
4
- data.tar.gz: dfbe08b1eaa5bfd9097e4ba9adbe68dead5660ee
2
+ SHA256:
3
+ metadata.gz: c185cbbf51aa9e484fad4fc0099a9b518d11954f5c5c2f11d03f9d086fdeee08
4
+ data.tar.gz: a8c356c5559e1ee1f02da859513badc848003d35cea3167ae66488c631309fca
5
5
  SHA512:
6
- metadata.gz: 1d177e56a051fed32219225b9a7c4a8ad289eeb87c96d4a03a1826df7e198352913850bb6754818a6be912a90777cd4569733710b9c6d921a1fcd31c0dc33a53
7
- data.tar.gz: fb1bfd02506a1d750f62e0ba045cbb1a12f0f6f0fd17a2d6065e4f973e2f0ad1191927626ccbbeb5184f5894ca960aece316df048041cae28bd797cd9cf9cdd2
6
+ metadata.gz: c028e25b401034206c66be282335e78e903edac248adaabecd0041bd5a187397f7bda59d894ed35ded3132aed762e3c8596d4aeeee92f6c5b93fbb9549245ec6
7
+ data.tar.gz: 4dc319fd28ae97aff269c0a6594a2cb271721da31c2ae48d7afd8927ccc352df1526fcfc486146ef55571788bca954de5649ce36a53b73c09767fb28eae99fb1
@@ -1,6 +1,4 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.4
5
- - 2.5
6
- before_install: gem install bundler -v 1.17.3
4
+ - 2.7
data/README.md CHANGED
@@ -75,6 +75,28 @@ Salestation allows and recommends you to define your own custom errors. This is
75
75
  })
76
76
  ```
77
77
 
78
+ ### Providing custom error fields
79
+
80
+ If you need to specify additional error fields you can use `from` method.
81
+ `from` accepts base error on which the rest of the response is built.
82
+ Base error must be a hash or implement `to_h` method.
83
+
84
+ Example:
85
+
86
+ ```
87
+ App::Errors::Conflict.from({details: 'details'}, message: 'message', debug_message: 'debug_message')
88
+ ```
89
+
90
+ Response:
91
+
92
+ ```javascript
93
+ {
94
+ "details": "details",
95
+ "message": "message",
96
+ "debug_message": "debug_message"
97
+ }
98
+ ```
99
+
78
100
  ### Using Extractors
79
101
 
80
102
  Salestation provides extractors to fetch parameters from the request and pass them to the chain.
@@ -142,14 +164,14 @@ end
142
164
 
143
165
  Salestation provides a StatsD middleware which can be used record request
144
166
  execution time. A `timing` call with elapsed seconds is made to the provided
145
- StatsD instance with `path`, `method`, `status` tags.
167
+ StatsD instance with `path`, `method`, `status` and `status_class` tags.
146
168
 
147
169
  ```ruby
148
170
  class Webapp < Sinatra::Base
149
171
  # ...
150
172
  use Salestation::Web::StatsdMiddleware,
151
173
  Statsd.new(host, port),
152
- metric: 'my-metric'
174
+ metric: 'my_service.response.time'
153
175
  end
154
176
  ```
155
177
 
@@ -157,7 +179,7 @@ You can configure per-request tags by defining `salestation.statsd.tags` in sina
157
179
 
158
180
  ```ruby
159
181
  def my_handler(env)
160
- env['salestation.statsd.tags'] = ['foo', 'bar']
182
+ env['salestation.statsd.tags'] = ['foo:bar']
161
183
  # ...
162
184
  end
163
185
  ```
@@ -7,7 +7,7 @@ require 'dry-types'
7
7
  module Salestation
8
8
  class App
9
9
  module Types
10
- include Dry::Types.module
10
+ include Dry::Types()
11
11
  end
12
12
 
13
13
  def initialize(env:, hooks: {})
@@ -3,43 +3,51 @@
3
3
  module Salestation
4
4
  class App
5
5
  module Errors
6
- class InvalidInput < Dry::Struct
6
+ class Error < Dry::Struct
7
+ attribute? :base_error, Types::Coercible::Hash
8
+
9
+ def self.from(base_error, overrides = {})
10
+ new(**overrides, base_error: base_error.to_h)
11
+ end
12
+ end
13
+
14
+ class InvalidInput < Error
7
15
  attribute :errors, Types::Strict::Hash
8
- attribute :hints, Types::Coercible::Hash.default({})
16
+ attribute :hints, Types::Coercible::Hash.default({}.freeze)
9
17
  attribute? :debug_message, Types::Strict::String
10
18
  end
11
19
 
12
- class DependencyCurrentlyUnavailable < Dry::Struct
20
+ class DependencyCurrentlyUnavailable < Error
13
21
  attribute :message, Types::Strict::String
14
22
  attribute? :debug_message, Types::Strict::String
15
23
  end
16
24
 
17
- class RequestedResourceNotFound < Dry::Struct
25
+ class RequestedResourceNotFound < Error
18
26
  attribute :message, Types::Strict::String
19
27
  attribute? :debug_message, Types::Strict::String
20
28
  end
21
29
 
22
- class Forbidden < Dry::Struct
30
+ class Forbidden < Error
23
31
  attribute :message, Types::Strict::String
24
32
  attribute? :debug_message, Types::Strict::String
25
33
  end
26
34
 
27
- class Conflict < Dry::Struct
35
+ class Conflict < Error
28
36
  attribute :message, Types::Strict::String
29
37
  attribute :debug_message, Types::Strict::String
30
38
  end
31
39
 
32
- class NotAcceptable < Dry::Struct
40
+ class NotAcceptable < Error
33
41
  attribute :message, Types::Strict::String
34
42
  attribute :debug_message, Types::Strict::String
35
43
  end
36
44
 
37
- class UnsupportedMediaType < Dry::Struct
45
+ class UnsupportedMediaType < Error
38
46
  attribute :message, Types::Strict::String
39
47
  attribute :debug_message, Types::Strict::String
40
48
  end
41
49
 
42
- class RequestEntityTooLarge < Dry::Struct
50
+ class RequestEntityTooLarge < Error
43
51
  attribute :message, Types::Strict::String
44
52
  attribute? :debug_message, Types::Strict::String
45
53
  end
@@ -8,7 +8,7 @@ require 'json'
8
8
  module Salestation
9
9
  class Web < Module
10
10
  module Types
11
- include Dry::Types.module
11
+ include Dry::Types()
12
12
  end
13
13
 
14
14
  def initialize(errors: {})
@@ -12,26 +12,27 @@ module Salestation
12
12
  App::Errors::DependencyCurrentlyUnavailable => -> (error) {
13
13
  Responses::ServiceUnavailable.new(
14
14
  message: error.message,
15
- debug_message: "Please try again later"
15
+ debug_message: "Please try again later",
16
+ base_error: error.base_error
16
17
  )
17
18
  },
18
19
  App::Errors::RequestedResourceNotFound => -> (error) {
19
- Responses::NotFound.new(message: error.message, debug_message: error.debug_message)
20
+ Responses::NotFound.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
20
21
  },
21
22
  App::Errors::Forbidden => -> (error) {
22
- Responses::Forbidden.new(message: error.message, debug_message: error.debug_message)
23
+ Responses::Forbidden.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
23
24
  },
24
25
  App::Errors::Conflict => -> (error) {
25
- Responses::Conflict.new(message: error.message, debug_message: error.debug_message)
26
+ Responses::Conflict.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
26
27
  },
27
28
  App::Errors::NotAcceptable => -> (error) {
28
- Responses::NotAcceptable.new(message: error.message, debug_message: error.debug_message)
29
+ Responses::NotAcceptable.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
29
30
  },
30
31
  App::Errors::UnsupportedMediaType => -> (error) {
31
- Responses::UnsupportedMediaType.new(message: error.message, debug_message: error.debug_message)
32
+ Responses::UnsupportedMediaType.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
32
33
  },
33
34
  App::Errors::RequestEntityTooLarge => -> (error) {
34
- Responses::RequestEntityTooLarge.new(message: error.message, debug_message: error.debug_message)
35
+ Responses::RequestEntityTooLarge.new(message: error.message, debug_message: error.debug_message, base_error: error.base_error)
35
36
  }
36
37
  }.freeze
37
38
 
@@ -32,27 +32,37 @@ module Salestation
32
32
  class Error < Response
33
33
  attribute :status, Types::Strict::Integer
34
34
  attribute :message, Types::Strict::String
35
- attribute :debug_message, Types::String.default('')
36
- attribute :context, Types::Hash.default({})
37
- attribute :headers, Types::Hash.default({})
35
+ attribute :debug_message, Types::Coercible::String.default('')
36
+ attribute :context, Types::Hash.default({}.freeze)
37
+ attribute :headers, Types::Hash.default({}.freeze)
38
+ attribute? :base_error, Types::Coercible::Hash
38
39
 
39
40
  def body
40
- {message: message, debug_message: debug_message}
41
+ # Merge into `base_error` to ensure standard fields are not overriden
42
+ (base_error || {}).merge(message: message, debug_message: debug_message)
43
+ end
44
+ end
45
+
46
+ class UnprocessableEntityError < Error
47
+ attribute :form_errors, Types::Hash.default({}.freeze)
48
+
49
+ def body
50
+ super.merge(form_errors: form_errors)
41
51
  end
42
52
  end
43
53
 
44
54
  class Success < Response
45
55
  attribute :status, Types::Strict::Integer
46
56
  attribute :body, Types::Strict::Hash | Types::Strict::Array
47
- attribute :headers, Types::Hash.default({})
57
+ attribute :headers, Types::Hash.default({}.freeze)
48
58
  end
49
59
 
50
60
  class UnprocessableEntityFromSchemaErrors
51
- def self.create(errors:, hints:)
61
+ def self.create(errors:, hints:, base_error: nil)
52
62
  message = parse_errors(errors)
53
63
  debug_message = parse_hints(hints)
54
64
 
55
- UnprocessableEntity.new(message: message, debug_message: debug_message)
65
+ UnprocessableEntity.new(message: message, debug_message: debug_message, form_errors: errors, base_error: base_error)
56
66
  end
57
67
 
58
68
  def self.parse_errors(errors)
@@ -99,7 +109,7 @@ module Salestation
99
109
  Conflict = Error.with_code(409)
100
110
  RequestEntityTooLarge = Error.with_code(413)
101
111
  UnsupportedMediaType = Error.with_code(415)
102
- UnprocessableEntity = Error.with_code(422)
112
+ UnprocessableEntity = UnprocessableEntityError.with_code(422)
103
113
 
104
114
  InternalError = Error.with_code(500)
105
115
  ServiceUnavailable = Error.with_code(503)
@@ -27,9 +27,10 @@ module Salestation
27
27
  end
28
28
 
29
29
  tags = [
30
- "path:#{ path }",
31
- "method:#{ method }",
32
- "status:#{ status }"
30
+ "path:#{path}",
31
+ "method:#{method}",
32
+ "status:#{status}",
33
+ "status_class:#{status / 100}xx"
33
34
  ] + env.fetch(EXTRA_TAGS_ENV_KEY, [])
34
35
 
35
36
  @statsd.timing(@metric, duration_ms(from: start), tags: tags)
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "salestation"
7
- spec.version = "3.5.1"
7
+ spec.version = "3.9.0"
8
8
  spec.authors = ["Glia TechMovers"]
9
9
  spec.email = ["techmovers@glia.com"]
10
10
 
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.13"
22
+ spec.add_development_dependency "bundler", "~> 2.0"
23
23
  spec.add_development_dependency "rake", "~> 13.0"
24
24
  spec.add_development_dependency "rspec", "~> 3.0"
25
25
  spec.add_development_dependency "pry", "~> 0.10.4"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: salestation
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.1
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glia TechMovers
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-31 00:00:00.000000000 Z
11
+ date: 2021-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.13'
19
+ version: '2.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.13'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -143,7 +143,7 @@ homepage: ''
143
143
  licenses:
144
144
  - MIT
145
145
  metadata: {}
146
- post_install_message:
146
+ post_install_message:
147
147
  rdoc_options: []
148
148
  require_paths:
149
149
  - lib
@@ -158,9 +158,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
160
  requirements: []
161
- rubyforge_project:
162
- rubygems_version: 2.6.14.4
163
- signing_key:
161
+ rubygems_version: 3.0.6
162
+ signing_key:
164
163
  specification_version: 4
165
164
  summary: ''
166
165
  test_files: []