fulfil-io 0.4.8 → 0.5.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/CHANGELOG.md +4 -0
- data/README.md +42 -4
- data/lib/fulfil/client.rb +20 -11
- data/lib/fulfil/error.rb +27 -0
- data/lib/fulfil/interactive_report.rb +1 -1
- data/lib/fulfil/response_handler.rb +52 -0
- data/lib/fulfil/response_parser.rb +2 -3
- data/lib/fulfil/version.rb +1 -1
- data/lib/fulfil.rb +4 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1100e113c9323c0fa742ece65d8a41923c060c382b1b97ad6c50ad20c550b5a9
|
4
|
+
data.tar.gz: 80535f7bea24218d958812bbd8e4ab789ce966c346e5dfa891369160fc04e536
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1ea6e403ab80bb108a90dff5f7ad58c39c228ed610ce497c631b5ae45a3ef5d2912100acd95ee33d7f2aa7c5609b71300c7a2322e1b2efcec688646573bf8da
|
7
|
+
data.tar.gz: d63d23350f0775bac73f28fdbabd0645798ed28a0466e7851ade38328a9f17e7a75982bc6bada6c1d951e4eb3ed0a4ffd872c79a6dc3c848f4308ddcfd11db16
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -129,10 +129,48 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
129
129
|
`rake test` to run the tests. You can also run `bin/console` for an interactive
|
130
130
|
prompt that will allow you to experiment.
|
131
131
|
|
132
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
133
|
-
|
134
|
-
|
135
|
-
|
132
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
133
|
+
|
134
|
+
### Release a new version
|
135
|
+
|
136
|
+
We're following semver for the release process of this gem. Make sure to apply the correct semver version for a new release.
|
137
|
+
|
138
|
+
To release a new version, run the `bin/release x.x.x`. That's it.
|
139
|
+
|
140
|
+
> **NOTE:** You don't have to add a v to the version you want to release. The release script will handle that for you.
|
141
|
+
|
142
|
+
### Testing
|
143
|
+
|
144
|
+
For non-client tests, create the test class or case.
|
145
|
+
|
146
|
+
For client tests, you'll need to add a couple steps. If running against a real
|
147
|
+
backend, you'll need to provide a couple of environment variables:
|
148
|
+
`FULFIL_SUBDOMAIN` and `FULFIL_TOKEN`. Additionally, pass `debug: true` to the
|
149
|
+
client instance in the test. This will output the response body. Webmock will
|
150
|
+
probably complain that real requests aren't allowed at this point, offering you
|
151
|
+
the stub. We don't need most of that.
|
152
|
+
|
153
|
+
We will need to capture the response body as JSON and store it in the
|
154
|
+
`test/fixtures` directory. Formatted for readability, please. You'll also need
|
155
|
+
to make note of the path and body of the request. Once you have that, you can
|
156
|
+
generate your stub.
|
157
|
+
|
158
|
+
To stub a request, use (or create) the helper method based on the verb. For
|
159
|
+
example, to stub a `GET` request, use `stub_fulfil_get`. Here's an example:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
def test_find_one
|
163
|
+
stub_fulfil_get('sale.sale/213112', 'sale_sale')
|
164
|
+
|
165
|
+
client = Fulfil::Client.new
|
166
|
+
response = client.find_one(model: 'sale.sale', id: 213_112)
|
167
|
+
|
168
|
+
assert_equal 213_112, response['id']
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
`stub_fulfil_get` takes two arguments: the URL path (after `/api/v2/model/`)
|
173
|
+
and the fixture file name to be returned.
|
136
174
|
|
137
175
|
## Contributing
|
138
176
|
|
data/lib/fulfil/client.rb
CHANGED
@@ -10,6 +10,12 @@ module Fulfil
|
|
10
10
|
OAUTH_TOKEN = ENV['FULFIL_TOKEN']
|
11
11
|
|
12
12
|
class Client
|
13
|
+
class InvalidClientError < StandardError
|
14
|
+
def message
|
15
|
+
'Client is not configured correctly.'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
13
19
|
class NotAuthorizedError < StandardError; end
|
14
20
|
|
15
21
|
class UnknownHTTPError < StandardError; end
|
@@ -24,6 +30,16 @@ module Fulfil
|
|
24
30
|
@debug = debug
|
25
31
|
@headers = headers
|
26
32
|
@headers.delete('X-API-KEY') if @token
|
33
|
+
|
34
|
+
raise InvalidClientError if invalid?
|
35
|
+
end
|
36
|
+
|
37
|
+
def invalid?
|
38
|
+
@subdomain.nil? || @subdomain.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid?
|
42
|
+
!invalid?
|
27
43
|
end
|
28
44
|
|
29
45
|
def find(model:, ids: [], id: nil, fields: %w[id rec_name])
|
@@ -125,19 +141,12 @@ module Fulfil
|
|
125
141
|
end
|
126
142
|
|
127
143
|
def request(endpoint:, verb: :get, **args)
|
144
|
+
raise InvalidClientError if invalid?
|
145
|
+
|
128
146
|
response = client.request(verb, endpoint, args)
|
147
|
+
Fulfil::ResponseHandler.new(response).verify!
|
129
148
|
|
130
|
-
|
131
|
-
response.parse
|
132
|
-
elsif response.code == 204
|
133
|
-
[]
|
134
|
-
elsif response.code == 401
|
135
|
-
error = response.parse
|
136
|
-
raise NotAuthorizedError, "Not authorized: #{error['error']}: #{error['error_description']}"
|
137
|
-
else
|
138
|
-
puts response.body.to_s
|
139
|
-
raise Error, 'Error encountered while processing response:'
|
140
|
-
end
|
149
|
+
response.parse
|
141
150
|
rescue HTTP::Error => e
|
142
151
|
puts e
|
143
152
|
raise UnknownHTTPError, 'Unhandled HTTP error encountered'
|
data/lib/fulfil/error.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fulfil
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
# The `Fulfil::HttpError` is raised whenever an API request returns a 400+ HTTP status code.
|
7
|
+
# See `Fulfil::ResponseHandler` for more information.
|
8
|
+
class HttpError < Error
|
9
|
+
attr_reader :metadata
|
10
|
+
|
11
|
+
def initialize(message, metadata = {})
|
12
|
+
@metadata = metadata
|
13
|
+
super(message)
|
14
|
+
end
|
15
|
+
|
16
|
+
class BadRequest < HttpError; end
|
17
|
+
class AuthorizationRequired < HttpError; end
|
18
|
+
class PaymentRequired < HttpError; end
|
19
|
+
class Forbidden < HttpError; end
|
20
|
+
class NotFound < HttpError; end
|
21
|
+
class MethodNotAllowed < HttpError; end
|
22
|
+
class NotAccepted < HttpError; end
|
23
|
+
class UnprocessableEntity < HttpError; end
|
24
|
+
class TooManyRequests < HttpError; end
|
25
|
+
class InternalServerError < HttpError; end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fulfil
|
4
|
+
# The `Fulfil::ResponseHandler` is parses the HTTP response from Fulfil. If it
|
5
|
+
# encounters an HTTP status code that indicates an error, it will raise an internal
|
6
|
+
# exception that the consumer can catch.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# Fulfil::ResponseHandler.new(@response).verify!
|
10
|
+
# => true
|
11
|
+
#
|
12
|
+
# Fulfil::ResponseHandler.new(@response).verify!
|
13
|
+
# => Fulfil::Error::BadRequest
|
14
|
+
class ResponseHandler
|
15
|
+
HTTP_ERROR_CODES = {
|
16
|
+
400 => Fulfil::HttpError::BadRequest,
|
17
|
+
401 => Fulfil::HttpError::AuthorizationRequired,
|
18
|
+
402 => Fulfil::HttpError::PaymentRequired,
|
19
|
+
403 => Fulfil::HttpError::Forbidden,
|
20
|
+
404 => Fulfil::HttpError::NotFound,
|
21
|
+
405 => Fulfil::HttpError::MethodNotAllowed,
|
22
|
+
406 => Fulfil::HttpError::NotAccepted,
|
23
|
+
422 => Fulfil::HttpError::UnprocessableEntity,
|
24
|
+
429 => Fulfil::HttpError::TooManyRequests,
|
25
|
+
500 => Fulfil::HttpError::InternalServerError
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
def initialize(response)
|
29
|
+
@response = response
|
30
|
+
@status_code = response.code
|
31
|
+
end
|
32
|
+
|
33
|
+
def verify!
|
34
|
+
return true unless @status_code >= 400
|
35
|
+
|
36
|
+
raise HTTP_ERROR_CODES.fetch(@status_code, Fulfil::HttpError).new(
|
37
|
+
response_body['error_description'],
|
38
|
+
{
|
39
|
+
body: @response.body,
|
40
|
+
headers: @response.headers,
|
41
|
+
status: @response.status
|
42
|
+
}
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def response_body
|
49
|
+
@response_body ||= @response.parse
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -41,7 +41,7 @@ module Fulfil
|
|
41
41
|
def self.group(key_value_tuples)
|
42
42
|
key_value_tuples
|
43
43
|
.group_by { |kv_tuple| kv_tuple[0][0] }
|
44
|
-
.map
|
44
|
+
.map do |group_key, kv_tuples|
|
45
45
|
if kv_tuples.length == 1
|
46
46
|
[group_key, mapped_value_field(value: kv_tuples[0][1])]
|
47
47
|
else
|
@@ -49,7 +49,7 @@ module Fulfil
|
|
49
49
|
attrs = kv_tuples[1..-1].map { |tuple| [tuple[0][1..-1], tuple[1]] }
|
50
50
|
[group_key, [['id', id[1]]].concat(group(attrs)).to_h]
|
51
51
|
end
|
52
|
-
|
52
|
+
end
|
53
53
|
end
|
54
54
|
|
55
55
|
def self.parse(item:)
|
@@ -57,5 +57,4 @@ module Fulfil
|
|
57
57
|
group(key_value_tuples).to_h
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
61
60
|
end
|
data/lib/fulfil/version.rb
CHANGED
data/lib/fulfil.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fulfil/version'
|
4
|
+
require 'fulfil/error'
|
2
5
|
require 'fulfil/client'
|
3
6
|
require 'fulfil/model'
|
4
7
|
require 'fulfil/interactive_report'
|
8
|
+
require 'fulfil/response_handler'
|
5
9
|
require 'fulfil/response_parser'
|
6
10
|
|
7
11
|
module Fulfil
|
8
|
-
class Error < StandardError; end
|
9
12
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fulfil-io
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-12-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: http
|
@@ -95,6 +95,20 @@ dependencies:
|
|
95
95
|
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: webmock
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
98
112
|
description:
|
99
113
|
email:
|
100
114
|
- chris@knowndecimal.com
|
@@ -111,9 +125,11 @@ files:
|
|
111
125
|
- Rakefile
|
112
126
|
- lib/fulfil.rb
|
113
127
|
- lib/fulfil/client.rb
|
128
|
+
- lib/fulfil/error.rb
|
114
129
|
- lib/fulfil/interactive_report.rb
|
115
130
|
- lib/fulfil/model.rb
|
116
131
|
- lib/fulfil/query.rb
|
132
|
+
- lib/fulfil/response_handler.rb
|
117
133
|
- lib/fulfil/response_parser.rb
|
118
134
|
- lib/fulfil/version.rb
|
119
135
|
homepage: https://github.com/knowndecimal/fulfil
|