fulfil-io 0.4.8 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|