glia-errors 0.5.1 → 0.9.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: 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: