glia-errors 0.5.1 → 0.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
2
  SHA256:
3
- metadata.gz: 603e9be432c9f317013ed3fb16c5861c75c844a3584d08ac3d4f39f1ba58ace4
4
- data.tar.gz: 7c88ac1f5d039ce62ec55f7ecb0ad4001138f48452a34d5697678c318873c753
3
+ metadata.gz: f6960566975ff5446a08dfc290bf2b1ebe1d3543df49e79ffb2ec24ad8f87763
4
+ data.tar.gz: 06f24196271555ebc4f5e2ac217399c8ad161fb0f6717cbe990fd8b7cc607da7
5
5
  SHA512:
6
- metadata.gz: 737bc0b2593e79b79fb41c61bafe9ec2ef6b7d4deb9cd3175167fd5bcd30dcb79b4d85bf1c366f8fff5cd6a35ec75e76ce2903919da336bba4b53f118a2e4311
7
- data.tar.gz: '0129e0df64a24f03a7b54d013f4c83b76ff1a66fd2e599fcdd7520859e45a4b68900e73a007e51042b171c9f4cbb391918dfdc6a49f9eabb96723ad1be50b245'
6
+ metadata.gz: bf8a1d4cc12a450424668ddf201f7cdf20293e8cca5c4269f6a405bbd91718b40e2e6011537cd39643728510fd75b0e51e05f84dcebf85ea5bcadb3a637f6ce2
7
+ data.tar.gz: 9ae41cf5a5f711c9a795ca7aeb6e67bc31c57c2926e05bd898b3645c4e4be6acfd1e94eafbbc687a6c0bb8bda512e0cbaa77a6c01f4c6a1b360149f8effcb231
data/README.md CHANGED
@@ -18,7 +18,18 @@ require 'glia/errors'
18
18
 
19
19
  ### For Glia developers
20
20
 
21
- #### Map from `dry-validation` result
21
+ #### Create Glia error manually
22
+
23
+ 1. Select error from the [error list](https://internal-docs.at.samo.io/glia-errors/elixir/api-reference.html#modules)
24
+ - Documentation is for Elixir, however, the errors are the same and their initiation is very similar
25
+ 2. Initialize the error according to the error documentation
26
+
27
+ Example:
28
+ ```
29
+ glia_error = Glia::Errors::ResourceNotFoundError.new(resource: :engagement)
30
+ ```
31
+
32
+ #### Create Glia error from `dry-validation` result
22
33
 
23
34
  Currently 2 `dry-validation` versions are supported:
24
35
  * `v0` up to `0.13`
@@ -29,11 +40,10 @@ schema = Dry::Validation.Schema do
29
40
  # ...
30
41
  end
31
42
  result = schema.(input)
32
- error = Glia::Errors.from_dry_validation_result(result)
33
- response = error.to_h
43
+ glia_error = Glia::Errors.from_dry_validation_result(result)
34
44
  ```
35
45
 
36
- #### Specifying mapping for custom error message
46
+ #### Create Glia error from `dry-validation` that contains custom errors
37
47
 
38
48
  If you have custom `dry-validation` predicates and error messages you can specify a custom error map.
39
49
  Custom error map takes priority over standard error mapping.
@@ -46,8 +56,15 @@ ERROR_MAP = {
46
56
  Glia::Errors::InvalidFormatError.new(field: field)
47
57
  end
48
58
  }
49
- error = Glia::Errors.from_dry_validation_result(result, ERROR_MAP)
50
- response = error.to_h
59
+ glia_error = Glia::Errors.from_dry_validation_result(result, ERROR_MAP)
60
+ ```
61
+
62
+ #### Convert Glia error to a hash
63
+
64
+ You can use this to convert Glia error to hash, so that later it can be converted to JSON.
65
+
66
+ ```ruby
67
+ glia_error.to_h
51
68
  ```
52
69
 
53
70
  ### For REST API integrators
data/glia-errors.gemspec CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'glia-errors'
8
- spec.version = '0.5.1'
8
+ spec.version = '0.9.0'
9
9
  spec.authors = ['Glia TechMovers']
10
10
  spec.email = ['techmovers@glia.com']
11
11
 
@@ -7,8 +7,8 @@ module Glia
7
7
  def initialize(error_details:, message: nil)
8
8
  super(
9
9
  type: INPUT_VALIDATION_ERROR,
10
- ref: "https://example.com/errors/#{INPUT_VALIDATION_ERROR}.html",
11
- message: message,
10
+ ref: create_ref(INPUT_VALIDATION_ERROR),
11
+ message: message || 'Input is invalid',
12
12
  error_details: error_details
13
13
  )
14
14
  end
@@ -18,8 +18,8 @@ module Glia
18
18
  def initialize(field:, message: nil)
19
19
  super(
20
20
  type: INVALID_NUMBER_ERROR,
21
- ref: "https://example.com/errors/#{INVALID_NUMBER_ERROR}.html",
22
- message: "#{humanize(field)} " + (message || 'value is invalid')
21
+ ref: create_ref(INVALID_NUMBER_ERROR),
22
+ message: message || "#{Naming.humanize(field)} value is invalid"
23
23
  )
24
24
  end
25
25
  end
@@ -28,8 +28,8 @@ module Glia
28
28
  def initialize(field:, message: nil)
29
29
  super(
30
30
  type: INVALID_VALUE_ERROR,
31
- ref: "https://example.com/errors/#{INVALID_VALUE_ERROR}.html",
32
- message: "#{humanize(field)} " + (message || 'value is invalid')
31
+ ref: create_ref(INVALID_VALUE_ERROR),
32
+ message: message || "#{Naming.humanize(field)} value is invalid"
33
33
  )
34
34
  end
35
35
  end
@@ -38,8 +38,8 @@ module Glia
38
38
  def initialize(field:, message: nil)
39
39
  super(
40
40
  type: INVALID_LENGTH_ERROR,
41
- ref: "https://example.com/errors/#{INVALID_LENGTH_ERROR}.html",
42
- message: "#{humanize(field)} " + (message || 'length is invalid')
41
+ ref: create_ref(INVALID_LENGTH_ERROR),
42
+ message: message || "#{Naming.humanize(field)} length is invalid"
43
43
  )
44
44
  end
45
45
  end
@@ -54,13 +54,34 @@ module Glia
54
54
 
55
55
  def initialize(field:, format: nil, message: nil)
56
56
  default_message =
57
- format ? "has invalid format, required format is #{format}" : 'has invalid format'
57
+ if format
58
+ "has invalid format, required format is #{humanize_format(format)}"
59
+ else
60
+ 'has invalid format'
61
+ end
58
62
  super(
59
63
  type: INVALID_FORMAT_ERROR,
60
- ref: "https://example.com/errors/#{INVALID_FORMAT_ERROR}.html",
61
- message: "#{humanize(field)} " + (message || default_message)
64
+ ref: create_ref(INVALID_FORMAT_ERROR),
65
+ message: message || "#{Naming.humanize(field)} #{default_message}"
62
66
  )
63
67
  end
68
+
69
+ private
70
+
71
+ def humanize_format(format)
72
+ case format
73
+ when Formats::DATE
74
+ 'ISO-8601 date'
75
+ when Formats::TIME
76
+ 'ISO-8601 time'
77
+ when Formats::DATE_TIME
78
+ 'ISO-8601 date and time'
79
+ when Formats::UUID
80
+ 'UUID'
81
+ else
82
+ raise 'Unexpected InvalidFormatError format'
83
+ end
84
+ end
64
85
  end
65
86
 
66
87
  class InvalidTypeError < Error
@@ -76,8 +97,8 @@ module Glia
76
97
  def initialize(field:, type:, message: nil)
77
98
  super(
78
99
  type: INVALID_TYPE_ERROR,
79
- ref: "https://example.com/errors/#{INVALID_TYPE_ERROR}.html",
80
- message: "#{humanize(field)} " + (message || "must be of type #{type}"),
100
+ ref: create_ref(INVALID_TYPE_ERROR),
101
+ message: message || "#{Naming.humanize(field)} must be of type #{type}",
81
102
  error_details: { type: type }
82
103
  )
83
104
  end
@@ -87,18 +108,23 @@ module Glia
87
108
  def initialize(field:, message: nil)
88
109
  super(
89
110
  type: MISSING_VALUE_ERROR,
90
- ref: "https://example.com/errors/#{MISSING_VALUE_ERROR}.html",
91
- message: "#{humanize(field)} " + (message || 'is missing')
111
+ ref: create_ref(MISSING_VALUE_ERROR),
112
+ message: message || "#{Naming.humanize(field)} is missing"
92
113
  )
93
114
  end
94
115
  end
95
116
 
96
117
  class UnknownError < Error
97
- def initialize(field:, message: nil)
118
+ def initialize(field: nil, message: nil)
98
119
  super(
99
120
  type: UNKNOWN_ERROR,
100
- ref: "https://example.com/errors/#{UNKNOWN_ERROR}.html",
101
- message: "#{humanize(field)} " + (message || 'validation failed with unknown error')
121
+ ref: create_ref(UNKNOWN_ERROR),
122
+ message:
123
+ if field
124
+ message || "#{Naming.humanize(field)} validation failed with unknown error"
125
+ else
126
+ message || 'Failed with unknown error'
127
+ end
102
128
  )
103
129
  end
104
130
  end
@@ -109,8 +135,8 @@ module Glia
109
135
 
110
136
  super(
111
137
  type: RESOURCE_NOT_FOUND_ERROR,
112
- ref: "https://example.com/errors/#{RESOURCE_NOT_FOUND_ERROR}.html",
113
- message: "#{humanize(resource)} " + (message || 'not found'),
138
+ ref: create_ref(RESOURCE_NOT_FOUND_ERROR),
139
+ message: message || "#{Naming.humanize(resource)} not found",
114
140
  error_details: { resource: resource }
115
141
  )
116
142
  end
@@ -122,8 +148,8 @@ module Glia
122
148
 
123
149
  super(
124
150
  type: NOT_VERIFIED_ERROR,
125
- ref: "https://example.com/errors/#{NOT_VERIFIED_ERROR}.html",
126
- message: "#{humanize(resource)} " + (message || 'is not verified'),
151
+ ref: create_ref(NOT_VERIFIED_ERROR),
152
+ message: message || "#{Naming.humanize(resource)} is not verified",
127
153
  error_details: { resource: resource }
128
154
  )
129
155
  end
@@ -136,25 +162,25 @@ module Glia
136
162
 
137
163
  default_message =
138
164
  "cannot be modified/deleted because it is associated to one or more #{
139
- humanize(associated_resource)
165
+ Naming.humanize(associated_resource)
140
166
  }(s)"
141
167
  super(
142
168
  type: REMAINING_ASSOCIATION_ERROR,
143
- ref: "https://example.com/errors/#{REMAINING_ASSOCIATION_ERROR}.html",
144
- message: "#{humanize(resource)} " + (message || default_message),
169
+ ref: create_ref(REMAINING_ASSOCIATION_ERROR),
170
+ message: message || "#{Naming.humanize(resource)} #{default_message}",
145
171
  error_details: { resource: resource, associated_resource: associated_resource }
146
172
  )
147
173
  end
148
174
  end
149
175
 
150
- class LimitExceededError < Error
176
+ class ResourceLimitExceededError < Error
151
177
  def initialize(resource:, max:, message: nil)
152
178
  assert_snake_case(resource)
153
179
 
154
180
  super(
155
181
  type: LIMIT_EXCEEDED_ERROR,
156
- ref: "https://example.com/errors/#{LIMIT_EXCEEDED_ERROR}.html",
157
- message: "#{humanize(resource)} " + (message || "count must not exceed #{max}"),
182
+ ref: create_ref(LIMIT_EXCEEDED_ERROR),
183
+ message: message || "#{Naming.humanize(resource)} count must not exceed #{max}",
158
184
  error_details: { resource: resource, max: max }
159
185
  )
160
186
  end
@@ -166,8 +192,8 @@ module Glia
166
192
 
167
193
  super(
168
194
  type: RESOURCE_ALREADY_EXISTS_ERROR,
169
- ref: "https://example.com/errors/#{RESOURCE_ALREADY_EXISTS_ERROR}.html",
170
- message: "#{humanize(resource)} " + (message || 'already exists'),
195
+ ref: create_ref(RESOURCE_ALREADY_EXISTS_ERROR),
196
+ message: message || "#{Naming.humanize(resource)} already exists",
171
197
  error_details: { resource: resource }
172
198
  )
173
199
  end
@@ -180,8 +206,8 @@ module Glia
180
206
 
181
207
  super(
182
208
  type: INVALID_RESOURCE_STATE_ERROR,
183
- ref: "https://example.com/errors/#{INVALID_RESOURCE_STATE_ERROR}.html",
184
- message: "#{humanize(resource)} " + (message || "is in invalid state: #{state}"),
209
+ ref: create_ref(INVALID_RESOURCE_STATE_ERROR),
210
+ message: message || "#{Naming.humanize(resource)} is in invalid state: #{state}",
185
211
  error_details: { resource: resource, state: state }
186
212
  )
187
213
  end
@@ -191,7 +217,7 @@ module Glia
191
217
  def initialize(message: nil)
192
218
  super(
193
219
  type: AUTHORIZATION_ERROR,
194
- ref: "https://example.com/errors/#{AUTHORIZATION_ERROR}.html",
220
+ ref: create_ref(AUTHORIZATION_ERROR),
195
221
  message: message || 'You do not have permissions to perform the action'
196
222
  )
197
223
  end
@@ -201,12 +227,101 @@ module Glia
201
227
  def initialize(message: nil)
202
228
  super(
203
229
  type: RECIPIENT_OPTED_OUT_ERROR,
204
- ref:
205
- 'https://docs.glia.com/glia-dev/reference/webhooks#example-engagementrequestfailure-event-with-fail_error',
230
+ ref: create_ref(RECIPIENT_OPTED_OUT_ERROR),
206
231
  message: message || 'Recipient has opted out'
207
232
  )
208
233
  end
209
234
  end
235
+
236
+ class RouteNotFoundError < Error
237
+ def initialize(message: nil)
238
+ super(
239
+ type: ROUTE_NOT_FOUND_ERROR,
240
+ ref: create_ref(ROUTE_NOT_FOUND_ERROR),
241
+ message: message || 'Route not found'
242
+ )
243
+ end
244
+ end
245
+
246
+ class MalformedInputError < Error
247
+ def initialize(message: nil)
248
+ super(
249
+ type: MALFORMED_INPUT_ERROR,
250
+ ref: create_ref(MALFORMED_INPUT_ERROR),
251
+ message: message || 'Request is malformed'
252
+ )
253
+ end
254
+ end
255
+
256
+ class CarrierError < Error
257
+ def initialize(message: nil)
258
+ super(
259
+ type: CARRIER_ERROR,
260
+ ref: create_ref(CARRIER_ERROR),
261
+ message: message || 'Downstream carrier issue occurred'
262
+ )
263
+ end
264
+ end
265
+
266
+ class GeographicPermissionError < Error
267
+ def initialize(message: nil)
268
+ super(
269
+ type: GEOGRAPHIC_PERMISSION_ERROR,
270
+ ref: create_ref(GEOGRAPHIC_PERMISSION_ERROR),
271
+ message: message || 'Insufficient permissions for geographic region'
272
+ )
273
+ end
274
+ end
275
+
276
+ class MessageBlockedError < Error
277
+ def initialize(message: nil)
278
+ super(
279
+ type: MESSAGE_BLOCKED_ERROR,
280
+ ref: create_ref(MESSAGE_BLOCKED_ERROR),
281
+ message: message || 'Message blocked or filtered'
282
+ )
283
+ end
284
+ end
285
+
286
+ class TelephonyProviderRateLimitExceededError < Error
287
+ def initialize(message: nil)
288
+ super(
289
+ type: TELEPHONY_PROVIDER_RATE_LIMIT_EXCEEDED_ERROR,
290
+ ref: create_ref(TELEPHONY_PROVIDER_RATE_LIMIT_EXCEEDED_ERROR),
291
+ message: message || 'Telephony provider message send rate limit exceeded'
292
+ )
293
+ end
294
+ end
295
+
296
+ class TelephonyProviderQueueLimitExceededError < Error
297
+ def initialize(message: nil)
298
+ super(
299
+ type: TELEPHONY_PROVIDER_QUEUE_LIMIT_EXCEEDED_ERROR,
300
+ ref: create_ref(TELEPHONY_PROVIDER_QUEUE_LIMIT_EXCEEDED_ERROR),
301
+ message: message || 'Telephony provider message send queue is full'
302
+ )
303
+ end
304
+ end
305
+
306
+ class TwilioMessagingServiceConfigurationError < Error
307
+ def initialize(message: nil)
308
+ super(
309
+ type: TWILIO_MESSAGING_SERVICE_CONFIGURATION_ERROR,
310
+ ref: create_ref(TWILIO_MESSAGING_SERVICE_CONFIGURATION_ERROR),
311
+ message: message || 'Invalid Twilio Messaging Service configuration'
312
+ )
313
+ end
314
+ end
315
+
316
+ class UnreachableDestinationError < Error
317
+ def initialize(message: nil)
318
+ super(
319
+ type: UNREACHABLE_DESTINATION_ERROR,
320
+ ref: create_ref(UNREACHABLE_DESTINATION_ERROR),
321
+ message: message || 'Destination is unreachable'
322
+ )
323
+ end
324
+ end
210
325
  # rubocop:enable Style/Documentation
211
326
  end
212
327
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './naming'
4
+
3
5
  module Glia
4
6
  module Errors
5
7
  # Base error
@@ -39,13 +41,8 @@ module Glia
39
41
  end
40
42
 
41
43
  def primitive?(details)
42
- details.nil? || [TrueClass, FalseClass, String, Integer, Float].include?(details.class)
43
- end
44
-
45
- # Converts from camel_case to capitalized more human readable value
46
- # first_name => "First name"
47
- def humanize(value)
48
- value.to_s.capitalize.gsub('_', ' ')
44
+ details.nil? ||
45
+ [TrueClass, FalseClass, String, Integer, Float, Symbol].include?(details.class)
49
46
  end
50
47
 
51
48
  def assert_snake_case(value)
@@ -53,6 +50,11 @@ module Glia
53
50
 
54
51
  raise ArgumentError, "Expected '#{value}' to be in snake case"
55
52
  end
53
+
54
+ def create_ref(type)
55
+ fragment = type.gsub('_', '-')
56
+ "https://docs.glia.com/glia-dev/reference/errors##{fragment}"
57
+ end
56
58
  end
57
59
  end
58
60
  end
@@ -19,6 +19,15 @@ module Glia
19
19
  INVALID_RESOURCE_STATE_ERROR = 'invalid_resource_state_error'
20
20
  AUTHORIZATION_ERROR = 'authorization_error'
21
21
  RECIPIENT_OPTED_OUT_ERROR = 'recipient_opted_out_error'
22
+ ROUTE_NOT_FOUND_ERROR = 'route_not_found_error'
23
+ MALFORMED_INPUT_ERROR = 'malformed_input_error'
24
+ CARRIER_ERROR = 'carrier_error'
25
+ GEOGRAPHIC_PERMISSION_ERROR = 'geographic_permission_error'
26
+ MESSAGE_BLOCKED_ERROR = 'message_blocked_error'
27
+ TELEPHONY_PROVIDER_RATE_LIMIT_EXCEEDED_ERROR = 'telephony_provider_rate_limit_exceeded_error'
28
+ TELEPHONY_PROVIDER_QUEUE_LIMIT_EXCEEDED_ERROR = 'telephony_provider_queue_limit_exceeded_error'
29
+ TWILIO_MESSAGING_SERVICE_CONFIGURATION_ERROR = 'twilio_messaging_service_configuration_error'
30
+ UNREACHABLE_DESTINATION_ERROR = 'unreachable_destination_error'
22
31
 
23
32
  # Server errors
24
33
  INTERNAL_SERVER_ERROR = 'internal_server_error'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Glia
4
+ module Errors
5
+ # Utilities for variable and resouce names
6
+ module Naming
7
+ # Converts from camel_case to more human readable value
8
+ # first_name => "First name"
9
+ # site_id => "Site ID"
10
+ def self.humanize(value)
11
+ result = value.to_s.split('_').map { |word| upcase_if_abbreviation(word) }.join(' ')
12
+
13
+ upcase_first(result)
14
+ end
15
+
16
+ ABBREVIATIONS = %w[id uuid saml sip sms mms].freeze
17
+ PLURAL_ABBREVIATIONS = %w[ids uuids].freeze
18
+
19
+ private_class_method def self.upcase_if_abbreviation(value)
20
+ if ABBREVIATIONS.include?(value)
21
+ value.upcase
22
+ elsif PLURAL_ABBREVIATIONS.include?(value)
23
+ value[0..-2].upcase.concat('s')
24
+ else
25
+ value
26
+ end
27
+ end
28
+
29
+ private_class_method def self.upcase_first(value)
30
+ value[0].upcase.concat(value[1..-1])
31
+ end
32
+ end
33
+ end
34
+ end
@@ -7,7 +7,7 @@ module Glia
7
7
  def initialize(message: nil)
8
8
  super(
9
9
  type: INTERNAL_SERVER_ERROR,
10
- ref: "https://example.com/errors/#{INTERNAL_SERVER_ERROR}.html",
10
+ ref: create_ref(INTERNAL_SERVER_ERROR),
11
11
  message: message || 'Internal server error'
12
12
  )
13
13
  end
@@ -17,7 +17,7 @@ module Glia
17
17
  def initialize(message: nil)
18
18
  super(
19
19
  type: SERVICE_UNAVAILABLE_ERROR,
20
- ref: "https://example.com/errors/#{SERVICE_UNAVAILABLE_ERROR}.html",
20
+ ref: create_ref(SERVICE_UNAVAILABLE_ERROR),
21
21
  message: message || 'Service unavailable'
22
22
  )
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glia-errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glia TechMovers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-02 00:00:00.000000000 Z
11
+ date: 2021-03-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: ''
14
14
  email:
@@ -37,6 +37,7 @@ files:
37
37
  - lib/glia/errors/error.rb
38
38
  - lib/glia/errors/error_types.rb
39
39
  - lib/glia/errors/mapper.rb
40
+ - lib/glia/errors/naming.rb
40
41
  - lib/glia/errors/server_errors.rb
41
42
  homepage:
42
43
  licenses: