easypost 4.13.0 → 5.0.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.
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