easypost 4.13.1 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +22 -1
- data/.gitignore +9 -11
- data/.rubocop.yml +6 -1
- data/CHANGELOG.md +19 -2
- data/Makefile +1 -1
- data/README.md +45 -38
- data/UPGRADE_GUIDE.md +119 -0
- data/VERSION +1 -1
- data/easycop.yml +3 -3
- data/easypost.gemspec +12 -10
- data/lib/easypost/client.rb +129 -0
- data/lib/easypost/connection.rb +2 -4
- data/lib/easypost/constants.rb +15 -0
- data/lib/easypost/errors/api/api_error.rb +106 -0
- data/lib/easypost/errors/api/connection_error.rb +6 -0
- data/lib/easypost/errors/api/external_api_error.rb +18 -0
- data/lib/easypost/errors/api/forbidden_error.rb +6 -0
- data/lib/easypost/errors/api/gateway_timeout_error.rb +6 -0
- data/lib/easypost/errors/api/internal_server_error.rb +6 -0
- data/lib/easypost/errors/api/invalid_request_error.rb +6 -0
- data/lib/easypost/errors/api/method_not_allowed_error.rb +6 -0
- data/lib/easypost/errors/api/not_found_error.rb +6 -0
- data/lib/easypost/errors/api/payment_error.rb +6 -0
- data/lib/easypost/errors/api/proxy_error.rb +6 -0
- data/lib/easypost/errors/api/rate_limit_error.rb +6 -0
- data/lib/easypost/errors/api/redirect_error.rb +6 -0
- data/lib/easypost/errors/api/retry_error.rb +6 -0
- data/lib/easypost/errors/api/service_unavailable_error.rb +6 -0
- data/lib/easypost/errors/api/ssl_error.rb +6 -0
- data/lib/easypost/errors/api/timeout_error.rb +6 -0
- data/lib/easypost/errors/api/unauthorized_error.rb +6 -0
- data/lib/easypost/errors/api/unknown_api_error.rb +6 -0
- data/lib/easypost/errors/easy_post_error.rb +7 -0
- data/lib/easypost/errors/end_of_pagination_error.rb +7 -0
- data/lib/easypost/errors/filtering_error.rb +4 -0
- data/lib/easypost/errors/invalid_object_error.rb +4 -0
- data/lib/easypost/errors/invalid_parameter_error.rb +11 -0
- data/lib/easypost/errors/missing_parameter_error.rb +9 -0
- data/lib/easypost/errors/signature_verification_error.rb +4 -0
- data/lib/easypost/errors.rb +31 -0
- data/lib/easypost/http_client.rb +62 -0
- data/lib/easypost/internal_utilities.rb +66 -0
- data/lib/easypost/models/address.rb +5 -0
- data/lib/easypost/models/api_key.rb +5 -0
- data/lib/easypost/models/base.rb +58 -0
- data/lib/easypost/models/batch.rb +5 -0
- data/lib/easypost/models/brand.rb +5 -0
- data/lib/easypost/{carbon_offset.rb → models/carbon_offset.rb} +1 -1
- data/lib/easypost/models/carrier_account.rb +5 -0
- data/lib/easypost/models/customs_info.rb +5 -0
- data/lib/easypost/models/customs_item.rb +5 -0
- data/lib/easypost/models/end_shipper.rb +5 -0
- data/lib/easypost/models/error.rb +21 -0
- data/lib/easypost/models/event.rb +5 -0
- data/lib/easypost/models/insurance.rb +6 -0
- data/lib/easypost/models/order.rb +9 -0
- data/lib/easypost/models/parcel.rb +5 -0
- data/lib/easypost/{payload.rb → models/payload.rb} +1 -1
- data/lib/easypost/models/payment_method.rb +5 -0
- data/lib/easypost/models/pickup.rb +9 -0
- data/lib/easypost/{pickup_rate.rb → models/pickup_rate.rb} +1 -1
- data/lib/easypost/{postage_label.rb → models/postage_label.rb} +1 -1
- data/lib/easypost/models/rate.rb +5 -0
- data/lib/easypost/models/referral.rb +5 -0
- data/lib/easypost/models/refund.rb +5 -0
- data/lib/easypost/models/report.rb +5 -0
- data/lib/easypost/models/scan_form.rb +6 -0
- data/lib/easypost/models/shipment.rb +10 -0
- data/lib/easypost/{tax_identifier.rb → models/tax_identifier.rb} +1 -1
- data/lib/easypost/models/tracker.rb +5 -0
- data/lib/easypost/models/user.rb +5 -0
- data/lib/easypost/models/webhook.rb +6 -0
- data/lib/easypost/models.rb +35 -0
- data/lib/easypost/services/address.rb +50 -0
- data/lib/easypost/services/api_key.rb +8 -0
- data/lib/easypost/services/base.rb +27 -0
- data/lib/easypost/services/batch.rb +53 -0
- data/lib/easypost/services/beta_rate.rb +12 -0
- data/lib/easypost/services/beta_referral_customer.rb +40 -0
- data/lib/easypost/services/billing.rb +75 -0
- data/lib/easypost/services/carrier_account.rb +44 -0
- data/lib/easypost/services/carrier_metadata.rb +22 -0
- data/lib/easypost/services/customs_info.rb +15 -0
- data/lib/easypost/services/customs_item.rb +15 -0
- data/lib/easypost/services/end_shipper.rb +31 -0
- data/lib/easypost/services/event.rb +32 -0
- data/lib/easypost/services/insurance.rb +26 -0
- data/lib/easypost/services/order.rb +30 -0
- data/lib/easypost/services/parcel.rb +16 -0
- data/lib/easypost/services/pickup.rb +40 -0
- data/lib/easypost/services/rate.rb +8 -0
- data/lib/easypost/services/referral_customer.rb +103 -0
- data/lib/easypost/services/refund.rb +26 -0
- data/lib/easypost/services/report.rb +42 -0
- data/lib/easypost/services/scan_form.rb +25 -0
- data/lib/easypost/services/shipment.rb +106 -0
- data/lib/easypost/services/tracker.rb +38 -0
- data/lib/easypost/services/user.rb +66 -0
- data/lib/easypost/services/webhook.rb +34 -0
- data/lib/easypost/services.rb +32 -0
- data/lib/easypost/util.rb +80 -187
- data/lib/easypost/utilities/constants.rb +5 -0
- data/lib/easypost/utilities/json.rb +23 -0
- data/lib/easypost/utilities/static_mapper.rb +73 -0
- data/lib/easypost/utilities/system.rb +36 -0
- data/lib/easypost.rb +12 -138
- metadata +147 -64
- data/lib/easypost/address.rb +0 -55
- data/lib/easypost/api_key.rb +0 -5
- data/lib/easypost/batch.rb +0 -52
- data/lib/easypost/beta/end_shipper.rb +0 -44
- data/lib/easypost/beta/payment_refund.rb +0 -5
- data/lib/easypost/beta/rate.rb +0 -14
- data/lib/easypost/beta/referral.rb +0 -158
- data/lib/easypost/beta.rb +0 -8
- data/lib/easypost/billing.rb +0 -72
- data/lib/easypost/brand.rb +0 -13
- data/lib/easypost/carrier_account.rb +0 -26
- data/lib/easypost/carrier_type.rb +0 -5
- data/lib/easypost/customs_info.rb +0 -9
- data/lib/easypost/customs_item.rb +0 -9
- data/lib/easypost/end_shipper.rb +0 -26
- data/lib/easypost/error.rb +0 -46
- data/lib/easypost/event.rb +0 -38
- data/lib/easypost/insurance.rb +0 -20
- data/lib/easypost/object.rb +0 -171
- data/lib/easypost/order.rb +0 -37
- data/lib/easypost/parcel.rb +0 -9
- data/lib/easypost/payment_method.rb +0 -12
- data/lib/easypost/pickup.rb +0 -47
- data/lib/easypost/rate.rb +0 -9
- data/lib/easypost/referral.rb +0 -117
- data/lib/easypost/refund.rb +0 -19
- data/lib/easypost/report.rb +0 -44
- data/lib/easypost/resource.rb +0 -124
- data/lib/easypost/scan_form.rb +0 -26
- data/lib/easypost/shipment.rb +0 -186
- data/lib/easypost/tracker.rb +0 -43
- data/lib/easypost/user.rb +0 -74
- data/lib/easypost/webhook.rb +0 -57
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b93e828aba22bcf673243120c7d51ab0d5bc813828204c5045ee7cbf4526bad2
|
|
4
|
+
data.tar.gz: 904d0537ad8f78924dee006329b59a1b07ce3496c33d07149684ec4219547978
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 64bbae9d00138cfc8634bb12a2d07b96dbfc951a93c2c983fa4a7da77e49bfc3d5ae2471ebca3ec84a5cb7c74fa88a1b851998c799119c071200bc37cd0645eb
|
|
7
|
+
data.tar.gz: 1d6910376670da796ee8daf8ed7c54e54591cd7f0770b7d363a38bd9d406a229e1df364fa7c16aa0f688830e171be82cb0ddb2f2331dd125a980158fad8d23c1
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -11,7 +11,7 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
strategy:
|
|
13
13
|
matrix:
|
|
14
|
-
rubyversion: ['2.
|
|
14
|
+
rubyversion: ['2.6', '2.7', '3.0', '3.1', '3.2']
|
|
15
15
|
steps:
|
|
16
16
|
- name: Checkout Repository
|
|
17
17
|
uses: actions/checkout@v3
|
|
@@ -48,3 +48,24 @@ jobs:
|
|
|
48
48
|
run: make lint
|
|
49
49
|
- name: Run security analysis
|
|
50
50
|
run: make scan
|
|
51
|
+
docs:
|
|
52
|
+
if: github.ref == 'refs/heads/master'
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
steps:
|
|
55
|
+
- name: Checkout Repository
|
|
56
|
+
uses: actions/checkout@v3
|
|
57
|
+
- name: Set up Ruby
|
|
58
|
+
uses: ruby/setup-ruby@v1
|
|
59
|
+
with:
|
|
60
|
+
ruby-version: '3.2'
|
|
61
|
+
rubygems: '3.0.0'
|
|
62
|
+
bundler-cache: true
|
|
63
|
+
- name: Install Dependencies
|
|
64
|
+
run: make install
|
|
65
|
+
- name: Generate Docs
|
|
66
|
+
run: make docs
|
|
67
|
+
- name: Deploy docs
|
|
68
|
+
uses: peaceiris/actions-gh-pages@v3
|
|
69
|
+
with:
|
|
70
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
71
|
+
publish_dir: docs
|
data/.gitignore
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
._*
|
|
2
|
+
.AppleDouble
|
|
1
3
|
.bundle
|
|
2
4
|
.config
|
|
5
|
+
.DS_Store
|
|
6
|
+
.env
|
|
3
7
|
.idea/
|
|
8
|
+
.LSOverride
|
|
9
|
+
.Spotlight-V100
|
|
10
|
+
.Trashes
|
|
4
11
|
*.gem
|
|
5
12
|
*.rbc
|
|
6
13
|
coverage
|
|
7
14
|
dist
|
|
15
|
+
docs
|
|
8
16
|
Gemfile.lock
|
|
17
|
+
Icon
|
|
9
18
|
InstalledFiles
|
|
10
19
|
lib/bundler/man
|
|
11
20
|
pkg
|
|
@@ -14,15 +23,4 @@ spec/reports
|
|
|
14
23
|
test/tmp
|
|
15
24
|
test/version_tmp
|
|
16
25
|
tmp
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# macOS
|
|
20
|
-
._*
|
|
21
|
-
.AppleDouble
|
|
22
|
-
.DS_Store
|
|
23
|
-
.env
|
|
24
|
-
.LSOverride
|
|
25
|
-
.Spotlight-V100
|
|
26
|
-
.Trashes
|
|
27
|
-
Icon
|
|
28
26
|
vendor/
|
data/.rubocop.yml
CHANGED
|
@@ -2,10 +2,15 @@ inherit_from: easycop.yml
|
|
|
2
2
|
|
|
3
3
|
AllCops:
|
|
4
4
|
SuggestExtensions: false
|
|
5
|
+
Exclude:
|
|
6
|
+
- bin/**/*
|
|
7
|
+
- docs/**/*
|
|
8
|
+
- examples/**/*
|
|
9
|
+
- vendor/bundle/**/*
|
|
5
10
|
# We are ignoring RSpec/FilePath because Simplecov doesn't play nice with nested spec files
|
|
6
11
|
RSpec/FilePath:
|
|
7
12
|
Enabled: false
|
|
8
13
|
# TODO: Remove this once we start using keyword arguments
|
|
9
14
|
Style/OptionalBooleanParameter:
|
|
10
15
|
Exclude:
|
|
11
|
-
- 'lib/easypost/
|
|
16
|
+
- 'lib/easypost/services/*.rb'
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
3
|
+
## v5.0.0 (2023-06-06)
|
|
4
|
+
|
|
5
|
+
See our [Upgrade Guide](UPGRADE_GUIDE.md#upgrading-from-4x-to-50) for more details.
|
|
6
|
+
|
|
7
|
+
- Library is now thread-safe. Closes GitHub Issue ([#183](https://github.com/EasyPost/easypost-ruby/issues/183))
|
|
8
|
+
- Initialize a `Client` object with an API key. Optionally set open and read timeout params
|
|
9
|
+
- Previous classes have been diverted into `Services` and `Models`
|
|
10
|
+
- All methods (i.e. `create`, `retrieve`, `all`) exist in services, accessed via property of the client (eg: `client.shipment.create()`)
|
|
11
|
+
- E.g. `bought_shipment = client.shipment.buy(shipment_id, rate)`
|
|
12
|
+
- Beta namespace changed from `easypost.beta.x` to `client.beta_x`
|
|
13
|
+
- References to `Referral` are now `ReferralCustomer` and `referral_customer` to match the API and docs
|
|
14
|
+
- References to `smartrate` are now `SmartRate` and `smart_rate` to match the API and docs
|
|
15
|
+
- Rename function `get_smartrates` to `get_smart_rates`
|
|
16
|
+
- Rename function `get_lowest_smartrate` to `get_lowest_smart_rate`
|
|
17
|
+
- Empty API response functions for `delete` return `true` instead of empty object
|
|
18
|
+
- Drops support for Ruby 2.5
|
|
19
|
+
- Bumps all dev dependencies
|
|
5
20
|
- Improves Error Deserialization to dynamically handle edge cases that have a bad format
|
|
21
|
+
- Adds `retrieve_estimated_delivery_date` function in Shipment
|
|
22
|
+
- Removes deprecated `endshipper` beta class, please use the GA one `EasyPost::Services::EndShipper`
|
|
6
23
|
|
|
7
24
|
## v4.13.0 (2023-04-04)
|
|
8
25
|
|
data/Makefile
CHANGED
data/README.md
CHANGED
|
@@ -24,9 +24,9 @@ A simple create & buy shipment example:
|
|
|
24
24
|
```ruby
|
|
25
25
|
require 'easypost'
|
|
26
26
|
|
|
27
|
-
EasyPost.api_key
|
|
27
|
+
client = EasyPost::Client.new(api_key: ENV['EASYPOST_TEST_API_KEY'])
|
|
28
28
|
|
|
29
|
-
shipment =
|
|
29
|
+
shipment = client.shipment.create(
|
|
30
30
|
from_address: {
|
|
31
31
|
company: 'EasyPost',
|
|
32
32
|
street1: '118 2nd Street',
|
|
@@ -53,39 +53,45 @@ shipment = EasyPost::Shipment.create(
|
|
|
53
53
|
},
|
|
54
54
|
)
|
|
55
55
|
|
|
56
|
-
shipment.buy(rate: shipment.lowest_rate)
|
|
56
|
+
bought_shipment = client.shipment.buy(shipment.id, rate: shipment.lowest_rate)
|
|
57
57
|
|
|
58
|
-
puts
|
|
58
|
+
puts bought_shipment
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
### Custom Connections
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
Pass in a lambda function as `custom_client_exec` when initializing a client that responds to `call(method, uri, headers, open_timeout, read_timeout, body = nil)` where:
|
|
64
|
+
- `uri` is the fully-qualified URL of the EasyPost endpoint, including query parameters (`Uri` object)
|
|
65
|
+
- `method` is the lowercase name of the HTTP method being used for the request (e.g. `:get`, `:post`, `:put`, `:delete`)
|
|
66
|
+
- `headers` is a hash with all headers needed for the request pre-populated, including authorization (`Hash` object)
|
|
67
|
+
- `open_timeout` is the number of seconds to wait for the connection to open (integer)
|
|
68
|
+
- `read_timeout` is the number of seconds to wait for one block to be read (integer)
|
|
69
|
+
- `body` is a string of the body data to be included in the request, or nil (e.g. GET or DELETE request) (string or `nil`)
|
|
70
|
+
|
|
71
|
+
The lambda function should return an object with `code` and `body` attributes, where:
|
|
72
|
+
- `code` is the HTTP response status code (integer)
|
|
73
|
+
- `body` is the response body (string)
|
|
64
74
|
|
|
65
75
|
#### Faraday
|
|
66
76
|
|
|
67
77
|
```ruby
|
|
68
78
|
require 'faraday'
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
json: response.headers['Content-Type'].start_with?('application/json'),
|
|
86
|
-
)
|
|
87
|
-
}
|
|
88
|
-
end
|
|
79
|
+
|
|
80
|
+
custom_connection = lambda { |method, uri, headers, _open_timeout, _read_timeout, body = nil|
|
|
81
|
+
conn = Faraday.new(url: uri.to_s, headers: headers) do |faraday|
|
|
82
|
+
faraday.adapter Faraday.default_adapter
|
|
83
|
+
end
|
|
84
|
+
conn.public_send(method, uri.path) { |request|
|
|
85
|
+
request.body = body if body
|
|
86
|
+
}.yield_self do |response|
|
|
87
|
+
OpenStruct.new(code: response.status, body: response.body)
|
|
88
|
+
end
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
my_client = described_class.new(
|
|
92
|
+
api_key: ENV['EASYPOST_API_KEY'],
|
|
93
|
+
custom_client_exec: custom_connection,
|
|
94
|
+
)
|
|
89
95
|
```
|
|
90
96
|
|
|
91
97
|
#### Typhoeus
|
|
@@ -93,27 +99,28 @@ end
|
|
|
93
99
|
```ruby
|
|
94
100
|
require 'typhoeus'
|
|
95
101
|
|
|
96
|
-
|
|
102
|
+
custom_connection = lambda { |method, uri, headers, _open_timeout, _read_timeout, body = nil|
|
|
97
103
|
Typhoeus.public_send(
|
|
98
104
|
method,
|
|
99
|
-
|
|
100
|
-
headers:
|
|
101
|
-
body: body
|
|
102
|
-
).yield_self
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
uri.to_s,
|
|
106
|
+
headers: headers,
|
|
107
|
+
body: body,
|
|
108
|
+
).yield_self do |response|
|
|
109
|
+
OpenStruct.new(code: response.code, body: response.body)
|
|
110
|
+
end
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
my_client = described_class.new(
|
|
114
|
+
api_key: ENV['EASYPOST_API_KEY'],
|
|
115
|
+
custom_client_exec: custom_connection,
|
|
116
|
+
)
|
|
110
117
|
```
|
|
111
118
|
|
|
112
119
|
## Documentation
|
|
113
120
|
|
|
114
121
|
API documentation can be found at: <https://easypost.com/docs/api>.
|
|
115
122
|
|
|
116
|
-
Library documentation can be found on the web at: <https://easypost.github.io/easypost-ruby/> or locally
|
|
123
|
+
Library documentation can be found on the web at: <https://easypost.github.io/easypost-ruby/> or by building them locally via the `make docs` command.
|
|
117
124
|
|
|
118
125
|
Upgrading major versions of this project? Refer to the [Upgrade Guide](UPGRADE_GUIDE.md).
|
|
119
126
|
|
data/UPGRADE_GUIDE.md
CHANGED
|
@@ -2,8 +2,127 @@
|
|
|
2
2
|
|
|
3
3
|
Use the following guide to assist in the upgrade process of the `easypost-ruby` library between major versions.
|
|
4
4
|
|
|
5
|
+
- [Upgrading from 4.x to 5.0](#upgrading-from-4x-to-50)
|
|
6
|
+
- [Upgrading from 3.x to 4.0](#upgrading-from-3x-to-40)
|
|
7
|
+
|
|
8
|
+
## Upgrading from 4.x to 5.0
|
|
9
|
+
|
|
10
|
+
### 5.0 High Impact Changes
|
|
11
|
+
|
|
12
|
+
- [New Client object](#50-thread-safe-with-client-object)
|
|
13
|
+
- [Updated Dependencies](#50-updated-dependencies)
|
|
14
|
+
- [Improved Error Handling](#50-improved-error-handling)
|
|
15
|
+
|
|
16
|
+
### 5.0 Medium Impact Changes
|
|
17
|
+
|
|
18
|
+
- [Corrected Naming Conventions](#50-corrected-naming-conventions)
|
|
19
|
+
|
|
20
|
+
### 5.0 Low Impact Changes
|
|
21
|
+
|
|
22
|
+
- [Beta Namespace Changed](#50-beta-namespace-changed)
|
|
23
|
+
|
|
24
|
+
## 5.0 Thread-Safe with Client Object
|
|
25
|
+
|
|
26
|
+
Likelihood of Impact: High
|
|
27
|
+
|
|
28
|
+
This library is now thread-safe with the introduction of a new `Client` object. Instead of defining a global API key that all requests use, you now create an `Client` object and pass your API key to it with optional open and read timeout params. You then call your desired functions against a `service` which are called against a `Client` object:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
# Old way
|
|
32
|
+
EasyPost.api_key = ENV['EASYPOST_API_KEY']
|
|
33
|
+
shipment = EasyPost::Shipment.retrieve('shp_...')
|
|
34
|
+
|
|
35
|
+
# New way
|
|
36
|
+
client = EasyPost::Client.new(api_key: ENV['EASYPOST_TEST_API_KEY'])
|
|
37
|
+
shipment = client.shipment.retrieve('shp_...')
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
All instance methods are now static with the exception of `lowest_rate` as these make API calls and require the Client object(EasyPost objects do not contain an API key to make API calls with).
|
|
41
|
+
|
|
42
|
+
Previously used `.save()` instance methods are now static `.update()` functions where you specify first the ID of the object you are updating and second, the parameters that need updating.
|
|
43
|
+
|
|
44
|
+
## 5.0 Updated Dependencies
|
|
45
|
+
|
|
46
|
+
Likelihood of Impact: High
|
|
47
|
+
|
|
48
|
+
**Ruby 2.6 Required**
|
|
49
|
+
|
|
50
|
+
easypost-ruby now requires Ruby 2.6 or greater.
|
|
51
|
+
|
|
52
|
+
**Dependencies**
|
|
53
|
+
|
|
54
|
+
All dependencies had minor version bumps.
|
|
55
|
+
|
|
56
|
+
## 5.0 Improved Error Handling
|
|
57
|
+
|
|
58
|
+
Likelihood of Impact: High
|
|
59
|
+
|
|
60
|
+
There are ~2 dozen new error types that extend either `ApiError` or `EasyPostError`.
|
|
61
|
+
|
|
62
|
+
New ApiErrors (extends EasyPostError):
|
|
63
|
+
|
|
64
|
+
- `ApiError`
|
|
65
|
+
- `ConnectionError`
|
|
66
|
+
- `ExternalApiError`
|
|
67
|
+
- `ForbiddenError`
|
|
68
|
+
- `GatewayTimeoutError`
|
|
69
|
+
- `InternalServerError`
|
|
70
|
+
- `InvalidRequestError`
|
|
71
|
+
- `MethodNotAllowedError`
|
|
72
|
+
- `NotFoundError`
|
|
73
|
+
- `PaymentError`
|
|
74
|
+
- `ProxyError`
|
|
75
|
+
- `RateLimitError`
|
|
76
|
+
- `RedirectError`
|
|
77
|
+
- `RetryError`
|
|
78
|
+
- `ServiceUnavailableError`
|
|
79
|
+
- `SSLError`
|
|
80
|
+
- `TimeoutError`
|
|
81
|
+
- `UnauthorizedError`
|
|
82
|
+
- `UnknownApiError`
|
|
83
|
+
|
|
84
|
+
New EasyPostErrors (extends builtin Exception):
|
|
85
|
+
|
|
86
|
+
- `EasyPostError`
|
|
87
|
+
- `EndOfPaginationError`
|
|
88
|
+
- `FilteringError`
|
|
89
|
+
- `InvalidObjectError`
|
|
90
|
+
- `InvalidParameterError`
|
|
91
|
+
- `MissingParameterError`
|
|
92
|
+
- `SignatureVerificationError`
|
|
93
|
+
|
|
94
|
+
ApiErrors will behave like the previous Error class did. They will include a `message`, `http_status`, and `http_body`. Additionally, a new `code` and `errors` keys are present and populate when available. This class extends the more generic `EasyPostError` which only contains a message, used for errors thrown directly from this library.
|
|
95
|
+
|
|
96
|
+
## 5.0 Corrected Naming Conventions
|
|
97
|
+
|
|
98
|
+
Likelihood of Impact: Medium
|
|
99
|
+
|
|
100
|
+
Occurances of `referral` are now `referral_customer` and `Referral` are now `ReferralCustomer` to match the documentation and API.
|
|
101
|
+
|
|
102
|
+
Occurances of `smartrate` are now `smart_rate` and `Smartrate` are now `SmartRate` to match the documentation and API.
|
|
103
|
+
|
|
104
|
+
Occurances of `scanform` are now `scan_form` and `Scanform` are now `ScanForm` to match the documentation and API.
|
|
105
|
+
|
|
106
|
+
Rename function `get_smartrates` to `get_smart_rates`
|
|
107
|
+
|
|
108
|
+
Rename function `get_lowest_smartrate` to `get_lowest_smart_rate`
|
|
109
|
+
|
|
110
|
+
## 5.0 Beta Namespace Changed
|
|
111
|
+
|
|
112
|
+
Likelihood of Impact: Low
|
|
113
|
+
|
|
114
|
+
Previously, the beta namespace was found at `easypost.beta.x` where `x` is the name of your model. Now, the beta namespace is simply prepended to the name of your service: `client.beta_x`. for instance, you can call `client.beta_referral_customer.add_payment_method()`.
|
|
115
|
+
|
|
116
|
+
## 5.0 Return True For Empty API Response
|
|
117
|
+
|
|
118
|
+
Likelihood of Impact: Low
|
|
119
|
+
|
|
120
|
+
Empty API response functions for `delete` return `true` instead of empty object
|
|
121
|
+
|
|
5
122
|
## Upgrading from 3.x to 4.0
|
|
6
123
|
|
|
124
|
+
**NOTICE:** v4 is deprecated.
|
|
125
|
+
|
|
7
126
|
### 4.0 High Impact Changes
|
|
8
127
|
|
|
9
128
|
* [Updating Dependencies](#40-updating-dependencies)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5.0.0
|
data/easycop.yml
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
require:
|
|
6
6
|
- rubocop-rspec
|
|
7
7
|
AllCops:
|
|
8
|
-
TargetRubyVersion: 2.
|
|
8
|
+
TargetRubyVersion: 2.6
|
|
9
9
|
NewCops: disable
|
|
10
10
|
Layout/BlockAlignment:
|
|
11
11
|
Enabled: true
|
|
@@ -41,7 +41,7 @@ Layout/FirstMethodArgumentLineBreak:
|
|
|
41
41
|
Enabled: true
|
|
42
42
|
Layout/LineLength:
|
|
43
43
|
Max: 120
|
|
44
|
-
|
|
44
|
+
AllowedPatterns:
|
|
45
45
|
- "(\\A|\\s)#"
|
|
46
46
|
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
|
47
47
|
Enabled: true
|
|
@@ -104,7 +104,7 @@ Metrics/ParameterLists:
|
|
|
104
104
|
Enabled: false
|
|
105
105
|
Metrics/AbcSize:
|
|
106
106
|
Enabled: false
|
|
107
|
-
Gemspec/
|
|
107
|
+
Gemspec/DeprecatedAttributeAssignment:
|
|
108
108
|
Enabled: true
|
|
109
109
|
Lint/AmbiguousAssignment: # new in 1.7
|
|
110
110
|
Enabled: true
|
data/easypost.gemspec
CHANGED
|
@@ -19,18 +19,20 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
end
|
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
21
21
|
spec.require_paths = ['lib']
|
|
22
|
-
spec.required_ruby_version = '>= 2.
|
|
22
|
+
spec.required_ruby_version = '>= 2.6'
|
|
23
23
|
|
|
24
|
-
spec.add_development_dependency 'brakeman', '~> 5.
|
|
24
|
+
spec.add_development_dependency 'brakeman', '~> 5.4'
|
|
25
|
+
spec.add_development_dependency 'faraday', '~> 2.7.5' # used for integration tests
|
|
25
26
|
spec.add_development_dependency 'pry', '~> 0.14'
|
|
26
|
-
spec.add_development_dependency 'psych', '~>
|
|
27
|
+
spec.add_development_dependency 'psych', '~> 5.1'
|
|
27
28
|
spec.add_development_dependency 'rake', '~> 13.0'
|
|
28
|
-
spec.add_development_dependency 'rdoc', '~> 6.
|
|
29
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
|
30
|
-
spec.add_development_dependency 'rubocop', '
|
|
31
|
-
spec.add_development_dependency 'rubocop-rspec', '
|
|
32
|
-
spec.add_development_dependency 'simplecov', '~> 0.
|
|
29
|
+
spec.add_development_dependency 'rdoc', '~> 6.5'
|
|
30
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
|
31
|
+
spec.add_development_dependency 'rubocop', '~> 1.49'
|
|
32
|
+
spec.add_development_dependency 'rubocop-rspec', '2.19' # pin to 2.19 because latest version doesn't support Ruby 2.6
|
|
33
|
+
spec.add_development_dependency 'simplecov', '~> 0.22'
|
|
33
34
|
spec.add_development_dependency 'simplecov-lcov', '~> 0.8'
|
|
34
|
-
spec.add_development_dependency '
|
|
35
|
-
spec.add_development_dependency '
|
|
35
|
+
spec.add_development_dependency 'typhoeus', '~> 1.4.0' # used for integration tests
|
|
36
|
+
spec.add_development_dependency 'vcr', '~> 6.1'
|
|
37
|
+
spec.add_development_dependency 'webmock', '~> 3.18'
|
|
36
38
|
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'services'
|
|
4
|
+
require_relative 'http_client'
|
|
5
|
+
require_relative 'internal_utilities'
|
|
6
|
+
require 'json'
|
|
7
|
+
|
|
8
|
+
class EasyPost::Client
|
|
9
|
+
attr_reader :open_timeout, :read_timeout, :api_base
|
|
10
|
+
|
|
11
|
+
# Initialize a new Client object
|
|
12
|
+
# @param api_key [String] the API key to be used for requests
|
|
13
|
+
# @param read_timeout [Integer] (60) the number of seconds to wait for a response before timing out
|
|
14
|
+
# @param open_timeout [Integer] (30) the number of seconds to wait for the connection to open before timing out
|
|
15
|
+
# @param api_base [String] ('https://api.easypost.com') the base URL for the API
|
|
16
|
+
# @param custom_client_exec [Proc] (nil) a custom client execution block to be used for requests instead of the default HTTP client (function signature: method, uri, headers, open_timeout, read_timeout, body = nil)
|
|
17
|
+
# @return [EasyPost::Client] the client object
|
|
18
|
+
def initialize(api_key:, read_timeout: 60, open_timeout: 30, api_base: 'https://api.easypost.com',
|
|
19
|
+
custom_client_exec: nil)
|
|
20
|
+
raise EasyPost::Errors::MissingParameterError.new('api_key') if api_key.nil?
|
|
21
|
+
|
|
22
|
+
@api_key = api_key
|
|
23
|
+
@api_base = api_base
|
|
24
|
+
@api_version = 'v2'
|
|
25
|
+
@read_timeout = read_timeout
|
|
26
|
+
@open_timeout = open_timeout
|
|
27
|
+
@lib_version = File.open(File.expand_path('../../VERSION', __dir__)).read.strip
|
|
28
|
+
|
|
29
|
+
# Make an HTTP client once, reuse it for all requests made by this client
|
|
30
|
+
# Configuration is immutable, so this is safe
|
|
31
|
+
@http_client = EasyPost::HttpClient.new(api_base, http_config, custom_client_exec)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
SERVICE_CLASSES = [
|
|
35
|
+
EasyPost::Services::Address,
|
|
36
|
+
EasyPost::Services::ApiKey,
|
|
37
|
+
EasyPost::Services::Batch,
|
|
38
|
+
EasyPost::Services::BetaRate,
|
|
39
|
+
EasyPost::Services::BetaReferralCustomer,
|
|
40
|
+
EasyPost::Services::Billing,
|
|
41
|
+
EasyPost::Services::CarrierAccount,
|
|
42
|
+
EasyPost::Services::CarrierMetadata,
|
|
43
|
+
EasyPost::Services::CustomsInfo,
|
|
44
|
+
EasyPost::Services::CustomsItem,
|
|
45
|
+
EasyPost::Services::EndShipper,
|
|
46
|
+
EasyPost::Services::Event,
|
|
47
|
+
EasyPost::Services::Insurance,
|
|
48
|
+
EasyPost::Services::Order,
|
|
49
|
+
EasyPost::Services::Parcel,
|
|
50
|
+
EasyPost::Services::Pickup,
|
|
51
|
+
EasyPost::Services::Rate,
|
|
52
|
+
EasyPost::Services::ReferralCustomer,
|
|
53
|
+
EasyPost::Services::Refund,
|
|
54
|
+
EasyPost::Services::Report,
|
|
55
|
+
EasyPost::Services::ScanForm,
|
|
56
|
+
EasyPost::Services::Shipment,
|
|
57
|
+
EasyPost::Services::Tracker,
|
|
58
|
+
EasyPost::Services::User,
|
|
59
|
+
EasyPost::Services::Webhook,
|
|
60
|
+
].freeze
|
|
61
|
+
|
|
62
|
+
# Loop over the SERVICE_CLASSES to automatically define the method and instance variable instead of manually define it
|
|
63
|
+
SERVICE_CLASSES.each do |cls|
|
|
64
|
+
define_method(EasyPost::InternalUtilities.to_snake_case(cls.name.split('::').last)) do
|
|
65
|
+
instance_variable_set("@#{EasyPost::InternalUtilities.to_snake_case(cls.name.split('::').last)}", cls.new(self))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Make an HTTP request
|
|
70
|
+
#
|
|
71
|
+
# @param method [Symbol] the HTTP Verb (get, method, put, post, etc.)
|
|
72
|
+
# @param endpoint [String] URI path of the resource
|
|
73
|
+
# @param cls [Class] the class to deserialize to
|
|
74
|
+
# @param body [Object] (nil) object to be dumped to JSON
|
|
75
|
+
# @param api_version [String] the version of API to hit
|
|
76
|
+
# @raise [EasyPost::Error] if the response has a non-2xx status code
|
|
77
|
+
# @return [Hash] JSON object parsed from the response body
|
|
78
|
+
def make_request(
|
|
79
|
+
method,
|
|
80
|
+
endpoint,
|
|
81
|
+
cls = EasyPost::Models::EasyPostObject,
|
|
82
|
+
body = nil,
|
|
83
|
+
api_version = EasyPost::InternalUtilities::Constants::API_VERSION
|
|
84
|
+
)
|
|
85
|
+
response = @http_client.request(method, endpoint, nil, body, api_version)
|
|
86
|
+
|
|
87
|
+
potential_error = EasyPost::Errors::ApiError.handle_api_error(response)
|
|
88
|
+
raise potential_error unless potential_error.nil?
|
|
89
|
+
|
|
90
|
+
EasyPost::InternalUtilities::Json.convert_json_to_object(response.body, cls)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
def http_config
|
|
96
|
+
http_config = {
|
|
97
|
+
read_timeout: @read_timeout,
|
|
98
|
+
open_timeout: @open_timeout,
|
|
99
|
+
headers: default_headers,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
http_config[:min_version] = OpenSSL::SSL::TLS1_2_VERSION
|
|
103
|
+
http_config
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def default_headers
|
|
107
|
+
{
|
|
108
|
+
'Content-Type' => 'application/json',
|
|
109
|
+
'User-Agent' => user_agent,
|
|
110
|
+
'Authorization' => authorization,
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def user_agent
|
|
115
|
+
ruby_version = EasyPost::InternalUtilities::System.ruby_version
|
|
116
|
+
ruby_patchlevel = EasyPost::InternalUtilities::System.ruby_patchlevel
|
|
117
|
+
|
|
118
|
+
"EasyPost/#{@api_version} " \
|
|
119
|
+
"RubyClient/#{@lib_version} " \
|
|
120
|
+
"Ruby/#{ruby_version}-p#{ruby_patchlevel} " \
|
|
121
|
+
"OS/#{EasyPost::InternalUtilities::System.os_name} " \
|
|
122
|
+
"OSVersion/#{EasyPost::InternalUtilities::System.os_version} " \
|
|
123
|
+
"OSArch/#{EasyPost::InternalUtilities::System.os_arch}"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def authorization
|
|
127
|
+
"Bearer #{@api_key}"
|
|
128
|
+
end
|
|
129
|
+
end
|
data/lib/easypost/connection.rb
CHANGED
|
@@ -10,9 +10,7 @@ EasyPost::Connection = Struct.new(:uri, :config, keyword_init: true) do
|
|
|
10
10
|
# @raise [EasyPost::Error] if the response has a non-2xx status code
|
|
11
11
|
# @return [Hash] JSON object parsed from the response body
|
|
12
12
|
def call(method, path, api_key = nil, body = nil)
|
|
13
|
-
if api_key.nil?
|
|
14
|
-
raise EasyPost::Error, 'No API key provided.'
|
|
15
|
-
end
|
|
13
|
+
raise EasyPost::Errors::MissingParameterError.new('api_key') if api_key.nil?
|
|
16
14
|
|
|
17
15
|
connection =
|
|
18
16
|
if config[:proxy]
|
|
@@ -49,7 +47,7 @@ EasyPost::Connection = Struct.new(:uri, :config, keyword_init: true) do
|
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
request = Net::HTTP.const_get(method.capitalize).new(path)
|
|
52
|
-
request.body = JSON.dump(EasyPost::
|
|
50
|
+
request.body = JSON.dump(EasyPost::InternalUtilities.objects_to_ids(body)) if body
|
|
53
51
|
|
|
54
52
|
EasyPost.default_headers.each_pair { |h, v| request[h] = v }
|
|
55
53
|
request['Authorization'] = EasyPost.authorization(api_key)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class EasyPost::Constants
|
|
4
|
+
API_ERROR_DETAILS_PARSING_ERROR = 'API error details could not be parsed.'
|
|
5
|
+
INVALID_PARAMETER = '%s is not a valid parameter.'
|
|
6
|
+
INVALID_PAYMENT_METHOD = 'The chosen payment method is not valid. Please try again.'
|
|
7
|
+
MISSING_REQUIRED_PARAMETER = 'Required parameter %s is missing.'
|
|
8
|
+
NO_MATCHING_RATES = 'No matching rates found.'
|
|
9
|
+
NO_MORE_PAGES = 'There are no more pages to retrieve.'
|
|
10
|
+
NO_PAYMENT_METHODS = 'Billing has not been setup for this user. Please add a payment method.'
|
|
11
|
+
STRIPE_CARD_CREATE_FAILED = 'Could not send card details to Stripe, please try again later.'
|
|
12
|
+
UNEXPECTED_HTTP_STATUS_CODE = 'Unexpected HTTP status code received: %s'
|
|
13
|
+
WEBHOOK_MISSING_SIGNATURE = 'Webhook received does not contain an HMAC signature.'
|
|
14
|
+
WEBHOOK_SIGNATURE_MISMATCH = 'Webhook received did not originate from EasyPost or had a webhook secret mismatch.'
|
|
15
|
+
end
|