easypost 4.13.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +22 -1
  3. data/.gitignore +9 -11
  4. data/.rubocop.yml +6 -1
  5. data/CHANGELOG.md +21 -0
  6. data/Makefile +1 -1
  7. data/README.md +45 -38
  8. data/UPGRADE_GUIDE.md +119 -0
  9. data/VERSION +1 -1
  10. data/easycop.yml +3 -3
  11. data/easypost.gemspec +12 -10
  12. data/lib/easypost/client.rb +129 -0
  13. data/lib/easypost/connection.rb +2 -4
  14. data/lib/easypost/constants.rb +15 -0
  15. data/lib/easypost/errors/api/api_error.rb +106 -0
  16. data/lib/easypost/errors/api/connection_error.rb +6 -0
  17. data/lib/easypost/errors/api/external_api_error.rb +18 -0
  18. data/lib/easypost/errors/api/forbidden_error.rb +6 -0
  19. data/lib/easypost/errors/api/gateway_timeout_error.rb +6 -0
  20. data/lib/easypost/errors/api/internal_server_error.rb +6 -0
  21. data/lib/easypost/errors/api/invalid_request_error.rb +6 -0
  22. data/lib/easypost/errors/api/method_not_allowed_error.rb +6 -0
  23. data/lib/easypost/errors/api/not_found_error.rb +6 -0
  24. data/lib/easypost/errors/api/payment_error.rb +6 -0
  25. data/lib/easypost/errors/api/proxy_error.rb +6 -0
  26. data/lib/easypost/errors/api/rate_limit_error.rb +6 -0
  27. data/lib/easypost/errors/api/redirect_error.rb +6 -0
  28. data/lib/easypost/errors/api/retry_error.rb +6 -0
  29. data/lib/easypost/errors/api/service_unavailable_error.rb +6 -0
  30. data/lib/easypost/errors/api/ssl_error.rb +6 -0
  31. data/lib/easypost/errors/api/timeout_error.rb +6 -0
  32. data/lib/easypost/errors/api/unauthorized_error.rb +6 -0
  33. data/lib/easypost/errors/api/unknown_api_error.rb +6 -0
  34. data/lib/easypost/errors/easy_post_error.rb +7 -0
  35. data/lib/easypost/errors/end_of_pagination_error.rb +7 -0
  36. data/lib/easypost/errors/filtering_error.rb +4 -0
  37. data/lib/easypost/errors/invalid_object_error.rb +4 -0
  38. data/lib/easypost/errors/invalid_parameter_error.rb +11 -0
  39. data/lib/easypost/errors/missing_parameter_error.rb +9 -0
  40. data/lib/easypost/errors/signature_verification_error.rb +4 -0
  41. data/lib/easypost/errors.rb +31 -0
  42. data/lib/easypost/http_client.rb +62 -0
  43. data/lib/easypost/internal_utilities.rb +66 -0
  44. data/lib/easypost/models/address.rb +5 -0
  45. data/lib/easypost/models/api_key.rb +5 -0
  46. data/lib/easypost/models/base.rb +58 -0
  47. data/lib/easypost/models/batch.rb +5 -0
  48. data/lib/easypost/models/brand.rb +5 -0
  49. data/lib/easypost/{carbon_offset.rb → models/carbon_offset.rb} +1 -1
  50. data/lib/easypost/models/carrier_account.rb +5 -0
  51. data/lib/easypost/models/customs_info.rb +5 -0
  52. data/lib/easypost/models/customs_item.rb +5 -0
  53. data/lib/easypost/models/end_shipper.rb +5 -0
  54. data/lib/easypost/models/error.rb +21 -0
  55. data/lib/easypost/models/event.rb +5 -0
  56. data/lib/easypost/models/insurance.rb +6 -0
  57. data/lib/easypost/models/order.rb +9 -0
  58. data/lib/easypost/models/parcel.rb +5 -0
  59. data/lib/easypost/{payload.rb → models/payload.rb} +1 -1
  60. data/lib/easypost/models/payment_method.rb +5 -0
  61. data/lib/easypost/models/pickup.rb +9 -0
  62. data/lib/easypost/{pickup_rate.rb → models/pickup_rate.rb} +1 -1
  63. data/lib/easypost/{postage_label.rb → models/postage_label.rb} +1 -1
  64. data/lib/easypost/models/rate.rb +5 -0
  65. data/lib/easypost/models/referral.rb +5 -0
  66. data/lib/easypost/models/refund.rb +5 -0
  67. data/lib/easypost/models/report.rb +5 -0
  68. data/lib/easypost/models/scan_form.rb +6 -0
  69. data/lib/easypost/models/shipment.rb +10 -0
  70. data/lib/easypost/{tax_identifier.rb → models/tax_identifier.rb} +1 -1
  71. data/lib/easypost/models/tracker.rb +5 -0
  72. data/lib/easypost/models/user.rb +5 -0
  73. data/lib/easypost/models/webhook.rb +6 -0
  74. data/lib/easypost/models.rb +35 -0
  75. data/lib/easypost/services/address.rb +50 -0
  76. data/lib/easypost/services/api_key.rb +8 -0
  77. data/lib/easypost/services/base.rb +27 -0
  78. data/lib/easypost/services/batch.rb +53 -0
  79. data/lib/easypost/services/beta_rate.rb +12 -0
  80. data/lib/easypost/services/beta_referral_customer.rb +40 -0
  81. data/lib/easypost/services/billing.rb +75 -0
  82. data/lib/easypost/services/carrier_account.rb +44 -0
  83. data/lib/easypost/services/carrier_metadata.rb +22 -0
  84. data/lib/easypost/services/customs_info.rb +15 -0
  85. data/lib/easypost/services/customs_item.rb +15 -0
  86. data/lib/easypost/services/end_shipper.rb +31 -0
  87. data/lib/easypost/services/event.rb +32 -0
  88. data/lib/easypost/services/insurance.rb +26 -0
  89. data/lib/easypost/services/order.rb +30 -0
  90. data/lib/easypost/services/parcel.rb +16 -0
  91. data/lib/easypost/services/pickup.rb +40 -0
  92. data/lib/easypost/services/rate.rb +8 -0
  93. data/lib/easypost/services/referral_customer.rb +103 -0
  94. data/lib/easypost/services/refund.rb +26 -0
  95. data/lib/easypost/services/report.rb +42 -0
  96. data/lib/easypost/services/scan_form.rb +25 -0
  97. data/lib/easypost/services/shipment.rb +106 -0
  98. data/lib/easypost/services/tracker.rb +38 -0
  99. data/lib/easypost/services/user.rb +66 -0
  100. data/lib/easypost/services/webhook.rb +34 -0
  101. data/lib/easypost/services.rb +32 -0
  102. data/lib/easypost/util.rb +80 -187
  103. data/lib/easypost/utilities/constants.rb +5 -0
  104. data/lib/easypost/utilities/json.rb +23 -0
  105. data/lib/easypost/utilities/static_mapper.rb +73 -0
  106. data/lib/easypost/utilities/system.rb +36 -0
  107. data/lib/easypost.rb +12 -138
  108. metadata +147 -64
  109. data/lib/easypost/address.rb +0 -55
  110. data/lib/easypost/api_key.rb +0 -5
  111. data/lib/easypost/batch.rb +0 -52
  112. data/lib/easypost/beta/end_shipper.rb +0 -44
  113. data/lib/easypost/beta/payment_refund.rb +0 -5
  114. data/lib/easypost/beta/rate.rb +0 -14
  115. data/lib/easypost/beta/referral.rb +0 -158
  116. data/lib/easypost/beta.rb +0 -8
  117. data/lib/easypost/billing.rb +0 -72
  118. data/lib/easypost/brand.rb +0 -13
  119. data/lib/easypost/carrier_account.rb +0 -26
  120. data/lib/easypost/carrier_type.rb +0 -5
  121. data/lib/easypost/customs_info.rb +0 -9
  122. data/lib/easypost/customs_item.rb +0 -9
  123. data/lib/easypost/end_shipper.rb +0 -26
  124. data/lib/easypost/error.rb +0 -32
  125. data/lib/easypost/event.rb +0 -38
  126. data/lib/easypost/insurance.rb +0 -20
  127. data/lib/easypost/object.rb +0 -171
  128. data/lib/easypost/order.rb +0 -37
  129. data/lib/easypost/parcel.rb +0 -9
  130. data/lib/easypost/payment_method.rb +0 -12
  131. data/lib/easypost/pickup.rb +0 -47
  132. data/lib/easypost/rate.rb +0 -9
  133. data/lib/easypost/referral.rb +0 -117
  134. data/lib/easypost/refund.rb +0 -19
  135. data/lib/easypost/report.rb +0 -44
  136. data/lib/easypost/resource.rb +0 -124
  137. data/lib/easypost/scan_form.rb +0 -26
  138. data/lib/easypost/shipment.rb +0 -186
  139. data/lib/easypost/tracker.rb +0 -43
  140. data/lib/easypost/user.rb +0 -74
  141. data/lib/easypost/webhook.rb +0 -57
data/lib/easypost/util.rb CHANGED
@@ -1,208 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Internal utilities helpful for this libraries operation.
4
- module EasyPost::Util
5
- attr_accessor :os_name, :os_version, :os_arch
6
-
7
- BY_PREFIX = {
8
- 'ak' => EasyPost::ApiKey,
9
- 'adr' => EasyPost::Address,
10
- 'bank' => EasyPost::PaymentMethod,
11
- 'batch' => EasyPost::Batch,
12
- 'brd' => EasyPost::Brand,
13
- 'ca' => EasyPost::CarrierAccount,
14
- 'card' => EasyPost::PaymentMethod,
15
- 'cstinfo' => EasyPost::CustomsInfo,
16
- 'cstitem' => EasyPost::CustomsItem,
17
- 'es' => EasyPost::EndShipper,
18
- 'evt' => EasyPost::Event,
19
- 'hook' => EasyPost::Webhook,
20
- 'ins' => EasyPost::Insurance,
21
- 'order' => EasyPost::Order,
22
- 'payload' => EasyPost::Payload,
23
- 'pickup' => EasyPost::Pickup,
24
- 'pickuprate' => EasyPost::PickupRate,
25
- 'pl' => EasyPost::PostageLabel,
26
- 'plrep' => EasyPost::Report,
27
- 'prcl' => EasyPost::Parcel,
28
- 'rate' => EasyPost::Rate,
29
- 'refrep' => EasyPost::Report,
30
- 'rfnd' => EasyPost::Refund,
31
- 'sf' => EasyPost::ScanForm,
32
- 'shp' => EasyPost::Shipment,
33
- 'shpinvrep' => EasyPost::Report,
34
- 'shprep' => EasyPost::Report,
35
- 'trk' => EasyPost::Tracker,
36
- 'trkrep' => EasyPost::Report,
37
- 'user' => EasyPost::User,
38
- }.freeze
39
-
40
- BY_TYPE = {
41
- 'Address' => EasyPost::Address,
42
- 'ApiKey' => EasyPost::ApiKey,
43
- 'BankAccount' => EasyPost::PaymentMethod,
44
- 'Batch' => EasyPost::Batch,
45
- 'Brand' => EasyPost::Brand,
46
- 'CarbonOffset' => EasyPost::CarbonOffset,
47
- 'CarrierAccount' => EasyPost::CarrierAccount,
48
- 'CreditCard' => EasyPost::PaymentMethod,
49
- 'CustomsInfo' => EasyPost::CustomsInfo,
50
- 'CustomsItem' => EasyPost::CustomsItem,
51
- 'EndShipper' => EasyPost::EndShipper,
52
- 'Event' => EasyPost::Event,
53
- 'Insurance' => EasyPost::Insurance,
54
- 'Order' => EasyPost::Order,
55
- 'Parcel' => EasyPost::Parcel,
56
- 'PaymentLogReport' => EasyPost::Report,
57
- 'Pickup' => EasyPost::Pickup,
58
- 'PickupRate' => EasyPost::PickupRate,
59
- 'PostageLabel' => EasyPost::PostageLabel,
60
- 'Rate' => EasyPost::Rate,
61
- 'Referral' => EasyPost::Beta::Referral,
62
- 'Refund' => EasyPost::Refund,
63
- 'RefundReport' => EasyPost::Report,
64
- 'Report' => EasyPost::Report,
65
- 'ScanForm' => EasyPost::ScanForm,
66
- 'Shipment' => EasyPost::Shipment,
67
- 'ShipmentInvoiceReport' => EasyPost::Report,
68
- 'ShipmentReport' => EasyPost::Report,
69
- 'TaxIdentifier' => EasyPost::TaxIdentifier,
70
- 'Tracker' => EasyPost::Tracker,
71
- 'TrackerReport' => EasyPost::Report,
72
- 'User' => EasyPost::User,
73
- 'Webhook' => EasyPost::Webhook,
74
- }.freeze
75
-
76
- def self.os_name
77
- case RUBY_PLATFORM
78
- when /linux/i
79
- 'Linux'
80
- when /darwin/i
81
- 'Darwin'
82
- when /cygwin|mswin|mingw|bccwin|wince|emx/i
83
- 'Windows'
84
- else
85
- 'Unknown'
86
- end
87
- end
88
-
89
- def self.os_version
90
- Gem::Platform.local.version
91
- end
92
-
93
- def self.os_arch
94
- Gem::Platform.local.cpu
95
- end
96
-
97
- # Form-encode a multi-layer dictionary to a one-layer dictionary.
98
- def self.form_encode_params(hash, parent_keys = [], parent_dict = {})
99
- result = parent_dict or {}
100
- keys = parent_keys or []
101
-
102
- hash.each do |key, value|
103
- if value.instance_of?(Hash)
104
- keys << key
105
- result = form_encode_params(value, keys, result)
106
- else
107
- dict_key = build_dict_key(keys + [key])
108
- result[dict_key] = value
109
- end
110
- end
111
- result
112
- end
113
-
114
- # Build a dict key from a list of keys.
115
- # Example: [code, number] -> code[number]
116
- def self.build_dict_key(keys)
117
- result = keys[0].to_s
118
-
119
- keys[1..-1].each do |key|
120
- result += "[#{key}]"
121
- end
122
-
123
- result
124
- end
125
-
126
- # Converts an object to an object ID.
127
- def self.objects_to_ids(obj)
128
- case obj
129
- when EasyPost::Resource
130
- { id: obj.id }
131
- when Hash
132
- result = {}
133
- obj.each { |k, v| result[k] = objects_to_ids(v) unless v.nil? }
134
- result
135
- when Array
136
- obj.map { |v| objects_to_ids(v) }
137
- else
138
- obj
139
- end
140
- end
141
-
142
- # Normalizes a list of strings.
143
- def self.normalize_string_list(lst)
144
- lst = lst.is_a?(String) ? lst.split(',') : Array(lst)
145
- lst.map(&:to_s).map(&:downcase).map(&:strip)
146
- end
147
-
148
- # Convert data to an EasyPost Object.
149
- def self.convert_to_easypost_object(response, api_key, parent = nil, name = nil)
150
- case response
151
- when Array
152
- response.map { |i| convert_to_easypost_object(i, api_key, parent) }
153
- when Hash
154
- # Determine class based on the "object" key in the JSON response
155
- cls_name = response[:object] || response['object']
156
- if cls_name
157
- # Use the "object" key value to look up the class
158
- cls = BY_TYPE[cls_name]
159
- else
160
- # Fallback to determining class based on the "id" prefix in the JSON response
161
- id = response[:id] || response['id']
162
- if id.nil? || id.index('_').nil?
163
- # ID not present or prefix not present (ID malformed)
164
- cls = EasyPost::EasyPostObject
165
- else
166
- # Parse the prefix from the ID and use it to look up the class
167
- cls_prefix = id[0..id.index('_')][0..-2]
168
- cls = BY_PREFIX[cls_prefix]
169
- end
170
- end
171
- # Fallback to using the generic class if other determination methods fail (or class lookup produced no results)
172
- cls ||= EasyPost::EasyPostObject
173
- cls.construct_from(response, api_key, parent, name)
174
- else
175
- # response is neither a Hash nor Array (used mostly when dealing with final values like strings, booleans, etc.)
176
- response
177
- end
178
- end
3
+ require 'easypost/constants'
179
4
 
5
+ # Client Library helper functions
6
+ module EasyPost::Util
180
7
  # Gets the lowest rate of an EasyPost object such as a Shipment, Order, or Pickup.
181
8
  # You can exclude by having `'!'` as the first element of your optional filter lists
182
9
  def self.get_lowest_object_rate(easypost_object, carriers = [], services = [], rates_key = 'rates')
183
10
  lowest_rate = nil
184
11
 
185
- carriers = EasyPost::Util.normalize_string_list(carriers)
12
+ carriers = EasyPost::InternalUtilities.normalize_string_list(carriers)
186
13
  negative_carriers = []
187
14
  carriers_copy = carriers.clone
188
15
  carriers_copy.each do |carrier|
189
16
  if carrier[0, 1] == '!'
190
- negative_carriers << carrier[1..-1]
17
+ negative_carriers << carrier[1..]
191
18
  carriers.delete(carrier)
192
19
  end
193
20
  end
194
21
 
195
- services = EasyPost::Util.normalize_string_list(services)
22
+ services = EasyPost::InternalUtilities.normalize_string_list(services)
196
23
  negative_services = []
197
24
  services_copy = services.clone
198
25
  services_copy.each do |service|
199
26
  if service[0, 1] == '!'
200
- negative_services << service[1..-1]
27
+ negative_services << service[1..]
201
28
  services.delete(service)
202
29
  end
203
30
  end
204
31
 
205
- easypost_object[rates_key].each do |rate|
32
+ easypost_object.send(rates_key).each do |rate|
206
33
  rate_carrier = rate.carrier.downcase
207
34
  if carriers.size.positive? && !carriers.include?(rate_carrier)
208
35
  next
@@ -224,7 +51,9 @@ module EasyPost::Util
224
51
  end
225
52
  end
226
53
 
227
- raise EasyPost::Error.new('No rates found.') if lowest_rate.nil?
54
+ if lowest_rate.nil?
55
+ raise EasyPost::Errors::FilteringError.new(EasyPost::Constants::NO_MATCHING_RATES)
56
+ end
228
57
 
229
58
  lowest_rate
230
59
  end
@@ -234,22 +63,22 @@ module EasyPost::Util
234
63
  def self.get_lowest_stateless_rate(stateless_rates, carriers = [], services = [])
235
64
  lowest_rate = nil
236
65
 
237
- carriers = EasyPost::Util.normalize_string_list(carriers)
66
+ carriers = EasyPost::InternalUtilities.normalize_string_list(carriers)
238
67
  negative_carriers = []
239
68
  carriers_copy = carriers.clone
240
69
  carriers_copy.each do |carrier|
241
70
  if carrier[0, 1] == '!'
242
- negative_carriers << carrier[1..-1]
71
+ negative_carriers << carrier[1..]
243
72
  carriers.delete(carrier)
244
73
  end
245
74
  end
246
75
 
247
- services = EasyPost::Util.normalize_string_list(services)
76
+ services = EasyPost::InternalUtilities.normalize_string_list(services)
248
77
  negative_services = []
249
78
  services_copy = services.clone
250
79
  services_copy.each do |service|
251
80
  if service[0, 1] == '!'
252
- negative_services << service[1..-1]
81
+ negative_services << service[1..]
253
82
  services.delete(service)
254
83
  end
255
84
  end
@@ -276,8 +105,72 @@ module EasyPost::Util
276
105
  end
277
106
  end
278
107
 
279
- raise EasyPost::Error.new('No rates found.') if lowest_rate.nil?
108
+ if lowest_rate.nil?
109
+ raise EasyPost::Errors::FilteringError.new(EasyPost::Constants::NO_MATCHING_RATES)
110
+ end
280
111
 
281
112
  lowest_rate
282
113
  end
114
+
115
+ # Converts a raw webhook event into an EasyPost object.
116
+ def self.receive_event(raw_input)
117
+ EasyPost::InternalUtilities::Json.convert_json_to_object(JSON.parse(raw_input), EasyPost::Models::EasyPostObject)
118
+ end
119
+
120
+ # Get the lowest SmartRate from a list of SmartRate.
121
+ def self.get_lowest_smart_rate(smart_rates, delivery_days, delivery_accuracy)
122
+ valid_delivery_accuracy_values = Set[
123
+ 'percentile_50',
124
+ 'percentile_75',
125
+ 'percentile_85',
126
+ 'percentile_90',
127
+ 'percentile_95',
128
+ 'percentile_97',
129
+ 'percentile_99',
130
+ ]
131
+ lowest_smart_rate = nil
132
+
133
+ unless valid_delivery_accuracy_values.include?(delivery_accuracy.downcase)
134
+ raise EasyPost::Errors::InvalidParameterError.new(
135
+ 'delivery_accuracy',
136
+ "Must be one of: #{valid_delivery_accuracy_values}",
137
+ )
138
+ end
139
+
140
+ smart_rates.each do |rate|
141
+ next if rate['time_in_transit'][delivery_accuracy] > delivery_days.to_i
142
+
143
+ if lowest_smart_rate.nil? || rate['rate'].to_f < lowest_smart_rate['rate'].to_f
144
+ lowest_smart_rate = rate
145
+ end
146
+ end
147
+
148
+ if lowest_smart_rate.nil?
149
+ raise EasyPost::Errors::FilteringError.new(EasyPost::Constants::NO_MATCHING_RATES)
150
+ end
151
+
152
+ lowest_smart_rate
153
+ end
154
+
155
+ # Validate a webhook by comparing the HMAC signature header sent from EasyPost to your shared secret.
156
+ # If the signatures do not match, an error will be raised signifying the webhook either did not originate
157
+ # from EasyPost or the secrets do not match. If the signatures do match, the `event_body` will be returned
158
+ # as JSON.
159
+ def self.validate_webhook(event_body, headers, webhook_secret)
160
+ easypost_hmac_signature = headers['X-Hmac-Signature']
161
+
162
+ if easypost_hmac_signature.nil?
163
+ raise EasyPost::Errors::SignatureVerificationError.new(EasyPost::Constants::WEBHOOK_MISSING_SIGNATURE)
164
+ end
165
+
166
+ encoded_webhook_secret = webhook_secret.unicode_normalize(:nfkd).encode('utf-8')
167
+
168
+ expected_signature = OpenSSL::HMAC.hexdigest('sha256', encoded_webhook_secret, event_body)
169
+ digest = "hmac-sha256-hex=#{expected_signature}"
170
+ unless digest == easypost_hmac_signature
171
+ raise EasyPost::Errors::SignatureVerificationError.new(EasyPost::Constants::WEBHOOK_SIGNATURE_MISMATCH)
172
+ end
173
+
174
+ JSON.parse(event_body)
175
+ end
283
176
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyPost::InternalUtilities::Constants
4
+ API_VERSION = 'v2'
5
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyPost::InternalUtilities::Json
4
+ def self.convert_json_to_object(data, cls = EasyPost::Models::EasyPostObject)
5
+ data = JSON.parse(data) if data.is_a?(String) # Parse JSON to a Hash or Array if it's a string
6
+ if data.is_a?(Array)
7
+ # Deserialize array data into an array of objects
8
+ data.map { |i| convert_json_to_object(i, cls) }
9
+ elsif data.is_a?(Hash)
10
+ # Deserialize hash data into a new object instance
11
+ cls.new(data)
12
+ else
13
+ # data is neither a Hash nor Array (but somehow was parsed as JSON? This should never happen)
14
+ data
15
+ end
16
+ rescue JSON::ParserError
17
+ data # Not JSON, return the original data (used mostly when dealing with final values like strings, booleans, etc.)
18
+ end
19
+
20
+ def self.http_response_is_json?(response)
21
+ response['Content-Type'] ? response['Content-Type'].start_with?('application/json') : false
22
+ end
23
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../models'
4
+
5
+ module EasyPost::InternalUtilities::StaticMapper
6
+ BY_PREFIX = {
7
+ 'adr' => EasyPost::Models::Address,
8
+ 'ak' => EasyPost::Models::ApiKey,
9
+ 'bank' => EasyPost::Models::PaymentMethod,
10
+ 'batch' => EasyPost::Models::Batch,
11
+ 'brd' => EasyPost::Models::Brand,
12
+ 'ca' => EasyPost::Models::CarrierAccount,
13
+ 'card' => EasyPost::Models::PaymentMethod,
14
+ 'cstinfo' => EasyPost::Models::CustomsInfo,
15
+ 'cstitem' => EasyPost::Models::CustomsItem,
16
+ 'es' => EasyPost::Models::EndShipper,
17
+ 'evt' => EasyPost::Models::Event,
18
+ 'hook' => EasyPost::Models::Webhook,
19
+ 'ins' => EasyPost::Models::Insurance,
20
+ 'order' => EasyPost::Models::Order,
21
+ 'payload' => EasyPost::Models::Payload,
22
+ 'pickup' => EasyPost::Models::Pickup,
23
+ 'pickuprate' => EasyPost::Models::PickupRate,
24
+ 'pl' => EasyPost::Models::PostageLabel,
25
+ 'plrep' => EasyPost::Models::Report,
26
+ 'prcl' => EasyPost::Models::Parcel,
27
+ 'rate' => EasyPost::Models::Rate,
28
+ 'refrep' => EasyPost::Models::Report,
29
+ 'rfnd' => EasyPost::Models::Refund,
30
+ 'sf' => EasyPost::Models::ScanForm,
31
+ 'shp' => EasyPost::Models::Shipment,
32
+ 'shpinvrep' => EasyPost::Models::Report,
33
+ 'shprep' => EasyPost::Models::Report,
34
+ 'trk' => EasyPost::Models::Tracker,
35
+ 'trkrep' => EasyPost::Models::Report,
36
+ 'user' => EasyPost::Models::User,
37
+ }.freeze
38
+
39
+ BY_TYPE = {
40
+ 'Address' => EasyPost::Models::Address,
41
+ 'ApiKey' => EasyPost::Models::ApiKey,
42
+ 'BankAccount' => EasyPost::Models::PaymentMethod,
43
+ 'Batch' => EasyPost::Models::Batch,
44
+ 'Brand' => EasyPost::Models::Brand,
45
+ 'CarbonOffset' => EasyPost::Models::CarbonOffset,
46
+ 'CarrierAccount' => EasyPost::Models::CarrierAccount,
47
+ 'CreditCard' => EasyPost::Models::PaymentMethod,
48
+ 'CustomsInfo' => EasyPost::Models::CustomsInfo,
49
+ 'CustomsItem' => EasyPost::Models::CustomsItem,
50
+ 'EndShipper' => EasyPost::Models::EndShipper,
51
+ 'Event' => EasyPost::Models::Event,
52
+ 'Insurance' => EasyPost::Models::Insurance,
53
+ 'Order' => EasyPost::Models::Order,
54
+ 'Parcel' => EasyPost::Models::Parcel,
55
+ 'PaymentLogReport' => EasyPost::Models::Report,
56
+ 'Pickup' => EasyPost::Models::Pickup,
57
+ 'PickupRate' => EasyPost::Models::PickupRate,
58
+ 'PostageLabel' => EasyPost::Models::PostageLabel,
59
+ 'Rate' => EasyPost::Models::Rate,
60
+ 'Refund' => EasyPost::Models::Refund,
61
+ 'RefundReport' => EasyPost::Models::Report,
62
+ 'Report' => EasyPost::Models::Report,
63
+ 'ScanForm' => EasyPost::Models::ScanForm,
64
+ 'Shipment' => EasyPost::Models::Shipment,
65
+ 'ShipmentInvoiceReport' => EasyPost::Models::Report,
66
+ 'ShipmentReport' => EasyPost::Models::Report,
67
+ 'TaxIdentifier' => EasyPost::Models::TaxIdentifier,
68
+ 'Tracker' => EasyPost::Models::Tracker,
69
+ 'TrackerReport' => EasyPost::Models::Report,
70
+ 'User' => EasyPost::Models::User,
71
+ 'Webhook' => EasyPost::Models::Webhook,
72
+ }.freeze
73
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyPost::InternalUtilities::System
4
+ def self.os_name
5
+ case RUBY_PLATFORM
6
+ when /linux/i
7
+ 'Linux'
8
+ when /darwin/i
9
+ 'Darwin'
10
+ when /cygwin|mswin|mingw|bccwin|wince|emx/i
11
+ 'Windows'
12
+ else
13
+ 'Unknown'
14
+ end
15
+ end
16
+
17
+ def self.os_version
18
+ Gem::Platform.local.version
19
+ end
20
+
21
+ def self.os_arch
22
+ Gem::Platform.local.cpu
23
+ end
24
+
25
+ def self.ruby_version
26
+ RUBY_VERSION
27
+ end
28
+
29
+ def self.ruby_patchlevel
30
+ RUBY_PATCHLEVEL
31
+ end
32
+
33
+ def self.lib_version
34
+ File.open(File.expand_path('../../VERSION', __dir__)).read.strip
35
+ end
36
+ end
data/lib/easypost.rb CHANGED
@@ -5,150 +5,24 @@ require 'cgi'
5
5
  require 'net/http'
6
6
 
7
7
  require 'easypost/version'
8
- require 'easypost/object'
9
- require 'easypost/resource'
10
- require 'easypost/error'
11
8
  require 'easypost/connection'
12
-
13
- # Resources
14
- require 'easypost/address'
15
- require 'easypost/api_key'
16
- require 'easypost/batch'
17
- require 'easypost/billing'
18
- require 'easypost/brand'
19
- require 'easypost/carbon_offset'
20
- require 'easypost/carrier_account'
21
- require 'easypost/carrier_type'
22
- require 'easypost/customs_info'
23
- require 'easypost/customs_item'
24
- require 'easypost/end_shipper'
25
- require 'easypost/event'
26
- require 'easypost/insurance'
27
- require 'easypost/order'
28
- require 'easypost/parcel'
29
- require 'easypost/payload'
30
- require 'easypost/payment_method' # deprecated
31
- require 'easypost/pickup_rate'
32
- require 'easypost/pickup'
33
- require 'easypost/postage_label'
34
- require 'easypost/rate'
35
- require 'easypost/referral'
36
- require 'easypost/refund'
37
- require 'easypost/report'
38
- require 'easypost/scan_form'
39
- require 'easypost/shipment'
40
- require 'easypost/tax_identifier'
41
- require 'easypost/tracker'
42
- require 'easypost/user'
43
- require 'easypost/webhook'
44
- require 'easypost/beta'
45
-
46
9
  require 'easypost/util'
47
10
 
48
- module EasyPost
49
- DEFAULT_API_BASE = 'https://api.easypost.com'
50
-
51
- class << self
52
- attr_accessor :api_key, :api_base
53
- attr_writer :default_connection
54
- end
55
-
56
- self.api_base = DEFAULT_API_BASE
57
-
58
- def self.user_agent
59
- @user_agent ||=
60
- "EasyPost/v2 RubyClient/#{EasyPost::VERSION} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} " \
61
- "OS/#{EasyPost::Util.os_name} OSVersion/#{EasyPost::Util.os_version} " \
62
- "OSArch/#{EasyPost::Util.os_arch}"
63
- end
64
-
65
- def self.default_headers
66
- @default_headers ||= {
67
- 'Content-Type' => 'application/json',
68
- 'User-Agent' => user_agent,
69
- }
70
- end
71
-
72
- def self.default_connection
73
- @default_connection ||= EasyPost::Connection.new(
74
- uri: URI(api_base),
75
- config: http_config,
76
- )
77
- end
78
-
79
- def self.authorization(key)
80
- "Basic #{Base64.strict_encode64("#{key}:")}"
81
- end
11
+ # Client
12
+ require 'easypost/client'
13
+ require 'easypost/http_client'
82
14
 
83
- # Reset the HTTP config.
84
- def self.reset_http_config
85
- http_config.clear
86
- self.default_connection = nil
87
- end
15
+ # Services
16
+ require 'easypost/services'
88
17
 
89
- def self.default_http_config
90
- http_config = {
91
- timeout: 60,
92
- open_timeout: 30,
93
- verify_ssl: OpenSSL::SSL::VERIFY_PEER,
94
- }
18
+ # Models
19
+ require 'easypost/models'
95
20
 
96
- ruby_version = Gem::Version.new(RUBY_VERSION)
97
- if ruby_version >= Gem::Version.new('2.5.0')
98
- http_config[:min_version] = OpenSSL::SSL::TLS1_2_VERSION
99
- else
100
- http_config[:ssl_version] = :TLSv1_2 # rubocop:disable Naming/VariableNumber
101
- end
21
+ # Exceptions
22
+ require 'easypost/errors'
102
23
 
103
- http_config
104
- end
24
+ # Internal Utilities
25
+ require 'easypost/internal_utilities'
105
26
 
106
- # Get the HTTP config.
107
- def self.http_config
108
- @http_config ||= default_http_config
109
- end
110
-
111
- # Set the HTTP config.
112
- def self.http_config=(http_config_params)
113
- http_config.merge!(http_config_params)
114
-
115
- self.default_connection = nil
116
- end
117
-
118
- # Create an EasyPost Client.
119
- #
120
- # @deprecated
121
- def self.make_client(url)
122
- EasyPost::Connection.new(uri: URI(url), config: http_config).create
123
- end
124
-
125
- # Make an HTTP request against the {default_connection}
126
- #
127
- # @param method [Symbol] the HTTP Verb (get, method, put, post, etc.)
128
- # @param path [String] URI path of the resource
129
- # @param requested_api_key [String] ({EasyPost.api_key}) key set Authorization header.
130
- # @param body [Object] (nil) object to be dumped to JSON
131
- # @raise [EasyPost::Error] if the response has a non-2xx status code
132
- # @return [Hash] JSON object parsed from the response body
133
- def self.make_request(method, path, api_key = nil, body = nil)
134
- default_connection.call(method, path, api_key || EasyPost.api_key, body)
135
- end
136
-
137
- def self.parse_response(status:, body:, json:)
138
- if status < 200 || status >= 300
139
- error = JSON.parse(body)['error']
140
-
141
- raise EasyPost::Error.new(
142
- error['message'],
143
- status,
144
- error['code'],
145
- error['errors'],
146
- body,
147
- )
148
- end
149
-
150
- json || !body.nil? && !body.match(/\A\s+\z/) ? JSON.parse(body) : body
151
- rescue JSON::ParserError
152
- raise "Invalid response object from API, unable to decode.\n#{body}"
153
- end
27
+ module EasyPost
154
28
  end