fulfil-io 0.4.8 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ee812b819341ca5960284540853594c9ec4ec07735f75672913cbdce1e7bf72
4
- data.tar.gz: 01f68a856b317a9ccc00946bac7ce06e638e9d016bf075a7e4130d17420f7c8a
3
+ metadata.gz: d85caade2af0ca4d9ede6a970d0c9b802960e5bc192a41d70eb9c70f153640b1
4
+ data.tar.gz: 13b43002ee089a9781221b7c42cef81a12474a11ccdb9f6e9df248eaabff8f84
5
5
  SHA512:
6
- metadata.gz: cb6a91114dea84e8c578f96ab2599ad03c036fc3222bf4b494f8cd32f79944b744660a2c0e4c7c45602e05e28f651eb6a6786a51e591950e04e36b291b3755a3
7
- data.tar.gz: 7d107fba6190bafa996da7cb9f081089d64d7d8bc1f1cbf2506e30b310e789b2567669b84208dc807456372e1330ebce5ac701b762f4d0c95b38551de18daf83
6
+ metadata.gz: 415418f4c4a54490b95d3823272096e481b064bf0be0f45cd44dc2c093af7616d93e56b46e0286447febf154f1187fbcbf31a0d3f3d8e456846a5590b636bc04
7
+ data.tar.gz: 854d989c8b343dabd2317850f578a7a2c37c9a19d04873b19eb278c278a78a51c94a928d5cf24f5a7265f05a63ff6d1dfcb5853971448843957827af9554bb9e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.4.9
2
+
3
+ * Add client tests and stub with Webmock.
4
+
1
5
  ## 0.4.8
2
6
 
3
7
  * Feature: Allow more params with InteractiveReport.
data/README.md CHANGED
@@ -1,40 +1,42 @@
1
- # Fulfil.io Rubygem
1
+ [![Tests](https://github.com/knowndecimal/fulfil/actions/workflows/tests.yml/badge.svg)](https://github.com/knowndecimal/fulfil/actions/workflows/tests.yml)
2
2
 
3
- [![CircleCI](https://circleci.com/gh/knowndecimal/fulfil.svg?style=svg&circle-token=da80ea6500af15b3a795a3913efe35742bab94c1)](https://circleci.com/gh/knowndecimal/fulfil)
3
+ # Fulfil.io Rubygem
4
4
 
5
- [Fulfil.io](https://fulfil.io)
5
+ A Ruby library for the [Fulfil.io](https://fulfil.io) API.
6
6
 
7
7
  ## Installation
8
8
 
9
9
  Add this line to your application's Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'fulfil-io', require: 'fulfil'
12
+ gem 'fulfil-io'
13
13
  ```
14
14
 
15
15
  And then execute:
16
16
 
17
- $ bundle install
17
+ ```shell
18
+ $ bundle install
19
+ ```
18
20
 
19
21
  Or install it yourself as:
20
22
 
21
- $ gem install fulfil-io
23
+ ```shell
24
+ $ gem install fulfil-io
25
+ ```
22
26
 
23
27
  ## Usage
24
28
 
25
29
  Environment variables:
26
30
 
27
- - FULFIL_SUBDOMAIN - required to be set.
28
- - FULFIL_TOKEN - required for oauth bearer authentication
29
- - FULFIL_API_KEY - required for authentication via the X-API-KEY request header
31
+ - **FULFIL_SUBDOMAIN:** - always required to use the gem.
32
+ - **FULFIL_OAUTH_TOKEN:** required for oauth bearer authentication
33
+ - **FULFIL_API_KEY:** required for authentication via the `X-API-KEY` request header
30
34
 
31
- **Note:** When FULFIL_TOKEN is present, the FULFIL_API_KEY will be ignored. So,
35
+ > **Note:** When `FULFIL_OAUTH_TOKEN` is present, the `FULFIL_API_KEY` will be ignored. So,
32
36
  if oauth doesn't work, returning an Unauthorized error, to use the
33
- FULFIL_API_KEY, the FULFIL_TOKEN shouldn't be specified.
37
+ `FULFIL_API_KEY`, the `FULFIL_OAUTH_TOKEN` shouldn't be specified.
34
38
 
35
39
  ```ruby
36
- require 'fulfil' # this is necessary only in case of running without bundler
37
-
38
40
  fulfil = Fulfil::Client.new # or, to enable request debugging, Fulfil::Client.new(debug: true)
39
41
 
40
42
  sale_model = Fulfil::Model.new(
@@ -43,7 +45,7 @@ sale_model = Fulfil::Model.new(
43
45
  )
44
46
 
45
47
  sales = sale_model.search(
46
- domain: [['id', '=', [10]]],
48
+ domain: [['id', '=', 10]],
47
49
  fields: ['id', 'rec_name', 'lines']
48
50
  )
49
51
 
@@ -123,16 +125,74 @@ report = Fulfil::Report.new(client: fulfil, report_name: 'account.tax.summary.ir
123
125
  report.execute(start_date: Date.new(2020, 12, 1), end_date: Date.new(2020, 12, 31))
124
126
  ```
125
127
 
128
+ ## Rate limits
129
+
130
+ Fulfil's API applies rate limits to the API requests that it receives. Every request is subject to throttling under the general limits. In addition, there are resource-based rate limits and throttles.
131
+
132
+ This gem exposes an API for checking your current rate limits (note: the gem only knows about the rate limit after a request to Fulfil's API has been made).
133
+
134
+ Whenever you reached the rate limit, the `Fulfil::RateLimitExceeded` exception is being raised. You can use the information on the `Fulfil.rate_limit` to find out what to do next.
135
+
136
+ ```ruby
137
+ $ Fulfil.rate_limit.requests_left?
138
+ => true
139
+
140
+ # The maximum number of requests you're permitted to make per second.
141
+ $ Fulfil.rate_limit.limit
142
+ => 9
143
+
144
+ # The time at which the current rate limit window resets in UTC epoch seconds.
145
+ $ Fulfil.rate_limit.resets_at
146
+ => #<DateTime: 2022-01-21T16:36:01-04:00 />
147
+ ```
126
148
  ## Development
127
149
 
128
150
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
129
151
  `rake test` to run the tests. You can also run `bin/console` for an interactive
130
152
  prompt that will allow you to experiment.
131
153
 
132
- To install this gem onto your local machine, run `bundle exec rake install`. To
133
- release a new version, update the version number in `version.rb`, and then run
134
- `bundle exec rake release`, which will create a git tag for the version, push
135
- git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
154
+ To install this gem onto your local machine, run `bundle exec rake install`.
155
+
156
+ ### Release a new version
157
+
158
+ We're following semver for the release process of this gem. Make sure to apply the correct semver version for a new release.
159
+
160
+ To release a new version, run the `bin/release x.x.x`. That's it.
161
+
162
+ > **NOTE:** You don't have to add a v to the version you want to release. The release script will handle that for you.
163
+
164
+ ### Testing
165
+
166
+ For non-client tests, create the test class or case.
167
+
168
+ For client tests, you'll need to add a couple steps. If running against a real
169
+ backend, you'll need to provide a couple of environment variables:
170
+ `FULFIL_SUBDOMAIN` and `FULFIL_OAUTH_TOKEN`. Additionally, pass `debug: true` to the
171
+ client instance in the test. This will output the response body. Webmock will
172
+ probably complain that real requests aren't allowed at this point, offering you
173
+ the stub. We don't need most of that.
174
+
175
+ We will need to capture the response body as JSON and store it in the
176
+ `test/fixtures` directory. Formatted for readability, please. You'll also need
177
+ to make note of the path and body of the request. Once you have that, you can
178
+ generate your stub.
179
+
180
+ To stub a request, use (or create) the helper method based on the verb. For
181
+ example, to stub a `GET` request, use `stub_fulfil_get`. Here's an example:
182
+
183
+ ```ruby
184
+ def test_find_one
185
+ stub_fulfil_get('sale.sale/213112', 'sale_sale')
186
+
187
+ client = Fulfil::Client.new
188
+ response = client.find_one(model: 'sale.sale', id: 213_112)
189
+
190
+ assert_equal 213_112, response['id']
191
+ end
192
+ ```
193
+
194
+ `stub_fulfil_get` takes two arguments: the URL path (after `/api/v2/model/`)
195
+ and the fixture file name to be returned.
136
196
 
137
197
  ## Contributing
138
198
 
data/lib/fulfil/client.rb CHANGED
@@ -7,9 +7,14 @@ require 'fulfil/response_parser'
7
7
  module Fulfil
8
8
  SUBDOMAIN = ENV['FULFIL_SUBDOMAIN']
9
9
  API_KEY = ENV['FULFIL_API_KEY']
10
- OAUTH_TOKEN = ENV['FULFIL_TOKEN']
11
10
 
12
11
  class Client
12
+ class InvalidClientError < StandardError
13
+ def message
14
+ 'Client is not configured correctly.'
15
+ end
16
+ end
17
+
13
18
  class NotAuthorizedError < StandardError; end
14
19
 
15
20
  class UnknownHTTPError < StandardError; end
@@ -18,12 +23,22 @@ module Fulfil
18
23
 
19
24
  class ResponseError < StandardError; end
20
25
 
21
- def initialize(subdomain: SUBDOMAIN, token: OAUTH_TOKEN, headers: { 'X-API-KEY' => API_KEY }, debug: false)
26
+ def initialize(subdomain: SUBDOMAIN, token: oauth_token, headers: { 'X-API-KEY' => API_KEY }, debug: false)
22
27
  @subdomain = subdomain
23
28
  @token = token
24
29
  @debug = debug
25
30
  @headers = headers
26
31
  @headers.delete('X-API-KEY') if @token
32
+
33
+ raise InvalidClientError if invalid?
34
+ end
35
+
36
+ def invalid?
37
+ @subdomain.nil? || @subdomain.empty?
38
+ end
39
+
40
+ def valid?
41
+ !invalid?
27
42
  end
28
43
 
29
44
  def find(model:, ids: [], id: nil, fields: %w[id rec_name])
@@ -96,6 +111,15 @@ module Fulfil
96
111
 
97
112
  private
98
113
 
114
+ def oauth_token
115
+ if ENV['FULFIL_TOKEN']
116
+ puts "You're using an deprecated environment variable. Please update your " \
117
+ 'FULFIL_TOKEN to FULFIL_OAUTH_TOKEN.'
118
+ end
119
+
120
+ ENV['FULFIL_OAUTH_TOKEN'] || ENV['FULFIL_TOKEN']
121
+ end
122
+
99
123
  def parse(result: nil, results: [])
100
124
  if result
101
125
  parse_single(result: result)
@@ -125,19 +149,12 @@ module Fulfil
125
149
  end
126
150
 
127
151
  def request(endpoint:, verb: :get, **args)
152
+ raise InvalidClientError if invalid?
153
+
128
154
  response = client.request(verb, endpoint, args)
155
+ Fulfil::ResponseHandler.new(response).verify!
129
156
 
130
- if response.status.ok? || response.status.created?
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
157
+ response.parse
141
158
  rescue HTTP::Error => e
142
159
  puts e
143
160
  raise UnknownHTTPError, 'Unhandled HTTP error encountered'
@@ -150,12 +167,10 @@ module Fulfil
150
167
  end
151
168
 
152
169
  def client
153
- return @client if defined?(@client)
154
-
155
- @client = HTTP.persistent(base_url).use(logging: @debug ? { logger: Logger.new(STDOUT) } : {})
156
- @client = @client.auth("Bearer #{@token}") if @token
157
- @client = @client.headers(@headers)
158
- @client
170
+ client = HTTP.use(logging: @debug ? { logger: Logger.new(STDOUT) } : {})
171
+ client = client.auth("Bearer #{@token}") if @token
172
+ client = client.headers(@headers)
173
+ client
159
174
  end
160
175
  end
161
176
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fulfil
4
+ class Error < StandardError; end
5
+
6
+ class RateLimitExceeded < Error; end
7
+
8
+ # The `Fulfil::HttpError` is raised whenever an API request returns a 400+ HTTP status code.
9
+ # See `Fulfil::ResponseHandler` for more information.
10
+ class HttpError < Error
11
+ attr_reader :metadata
12
+
13
+ def initialize(message, metadata = {})
14
+ @metadata = metadata
15
+ super(message)
16
+ end
17
+
18
+ class BadRequest < HttpError; end
19
+ class AuthorizationRequired < HttpError; end
20
+ class PaymentRequired < HttpError; end
21
+ class Forbidden < HttpError; end
22
+ class NotFound < HttpError; end
23
+ class MethodNotAllowed < HttpError; end
24
+ class NotAccepted < HttpError; end
25
+ class UnprocessableEntity < HttpError; end
26
+ class TooManyRequests < HttpError; end
27
+ class InternalServerError < HttpError; end
28
+ end
29
+ end
@@ -37,4 +37,4 @@ module Fulfil
37
37
  }
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fulfil
4
+ # The `Fulfil::RateLimit` allows clients to keep track of their API usage and
5
+ # to analyze Fulfil's response HTTP headers.
6
+ class RateLimit
7
+ attr_accessor :limit, :requests_left, :resets_at
8
+
9
+ # Analyses the rate limit based on the response headers from Fulfil.
10
+ # @param headers [HTTP::Headers] The HTTP response headers from Fulfil.
11
+ # @return [Fulfil::RateLimit]
12
+ def analyse!(headers)
13
+ rate_limit_headers = RateLimitHeaders.new(headers)
14
+
15
+ self.limit = rate_limit_headers.limit
16
+ self.requests_left = rate_limit_headers.requests_left
17
+ self.resets_at = rate_limit_headers.resets_at
18
+
19
+ raise Fulfil::RateLimitExceeded unless requests_left?
20
+ end
21
+
22
+ # Returns whether there are any requests left in the current rate limit window.
23
+ # @return [Boolean]
24
+ def requests_left?
25
+ requests_left&.positive?
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fulfil
4
+ # The `Fulfil::RateLimitHeaders` parses Fulfil HTTP rate limit headers and
5
+ # formats them to a more usable format.
6
+ class RateLimitHeaders
7
+ # Test suites might mock (or at least should mock) the requests to Fulfil.
8
+ # However, most of these test suites will not mock the response headers.
9
+ # To make sure those test suites don't break, we're setting some defaults for them.
10
+ DEFAULT_REQUEST_LIMIT = 10
11
+ DEFAULT_REQUESTS_LEFT = 9
12
+ DEFAULT_RESETS_AT = nil
13
+
14
+ attr_reader :limit, :requests_left, :resets_at
15
+
16
+ def initialize(headers = {})
17
+ self.limit = headers['X-RateLimit-Limit'] || DEFAULT_REQUEST_LIMIT
18
+ self.requests_left = headers['X-RateLimit-Remaining'] || DEFAULT_REQUESTS_LEFT
19
+ self.resets_at = headers['X-RateLimit-Reset'] || DEFAULT_RESETS_AT
20
+ end
21
+
22
+ # Sets the maximum number of requests you're permitted to make per second.
23
+ # @param value [String] The maximum number of requests per second.
24
+ # @return [Integer] The maximum number of requests per second.
25
+ def limit=(value)
26
+ @limit = value.to_i
27
+ end
28
+
29
+ # Sets number of requests remaining in the current rate limit window.
30
+ # @param value [String] The remaining number of requests for the current time window.
31
+ # @return [Integer] The remaining number of requests for the current time window.
32
+ def requests_left=(value)
33
+ @requests_left = value.to_i
34
+ end
35
+
36
+ # Sets the time at which the current rate limit window resets in UTC epoch seconds.
37
+ # @param value [Integer|nil] Time as an integer in UTC epoch seconds.
38
+ # @return [DataTime|nil] The moment the rate limit resets.
39
+ def resets_at=(value)
40
+ @resets_at =
41
+ if value.nil?
42
+ nil
43
+ else
44
+ Time.at(value.to_i).utc.to_datetime
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,61 @@
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
+ verify_rate_limits!
35
+ verify_http_status_code!
36
+ end
37
+
38
+ private
39
+
40
+ def verify_rate_limits!
41
+ Fulfil.rate_limit.analyse!(@response.headers)
42
+ end
43
+
44
+ def verify_http_status_code!
45
+ return true unless @status_code >= 400
46
+
47
+ raise HTTP_ERROR_CODES.fetch(@status_code, Fulfil::HttpError).new(
48
+ response_body['error_description'],
49
+ {
50
+ body: @response.body,
51
+ headers: @response.headers,
52
+ status: @response.status
53
+ }
54
+ )
55
+ end
56
+
57
+ def response_body
58
+ @response_body ||= @response.parse
59
+ end
60
+ end
61
+ 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 { |group_key, kv_tuples|
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fulfil
4
- VERSION = '0.4.8'
4
+ VERSION = "0.6.1"
5
5
  end
data/lib/fulfil-io.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # By convention, Bundler will attempt to load the `fulfil/io.rb` or `fulfil-io.rb` file.
4
+ # See https://guides.rubygems.org/name-your-gem/
5
+ #
6
+ # Due to this convention, the developer using this gem will need to manually
7
+ # require fulfil in the Gemfile or anywhere else in their application.
8
+ #
9
+ # To make it a little bit more convenient, we've added the `fulfil-io.rb` file
10
+ # that is loaded by default by Bundler and it's only job is to include all of
11
+ # the other gem files.
12
+
13
+ require 'fulfil'
data/lib/fulfil.rb CHANGED
@@ -1,9 +1,19 @@
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
 
11
+ # Rate limiting
12
+ require 'fulfil/rate_limit'
13
+ require 'fulfil/rate_limit_headers'
14
+
7
15
  module Fulfil
8
- class Error < StandardError; end
16
+ def self.rate_limit
17
+ @rate_limit ||= RateLimit.new
18
+ end
9
19
  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.8
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Moore
@@ -9,22 +9,28 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-11-30 00:00:00.000000000 Z
12
+ date: 2022-04-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: 4.4.1
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 5.1.0
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
- - - "~>"
28
+ - - ">="
26
29
  - !ruby/object:Gem::Version
27
30
  version: 4.4.1
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 5.1.0
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: bundler
30
36
  requirement: !ruby/object:Gem::Requirement
@@ -95,6 +101,40 @@ dependencies:
95
101
  - - ">="
96
102
  - !ruby/object:Gem::Version
97
103
  version: '0'
104
+ - !ruby/object:Gem::Dependency
105
+ name: webmock
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ - !ruby/object:Gem::Dependency
119
+ name: dotenv
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.7'
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: 2.7.6
128
+ type: :development
129
+ prerelease: false
130
+ version_requirements: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - "~>"
133
+ - !ruby/object:Gem::Version
134
+ version: '2.7'
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 2.7.6
98
138
  description:
99
139
  email:
100
140
  - chris@knowndecimal.com
@@ -109,11 +149,16 @@ files:
109
149
  - LICENSE.txt
110
150
  - README.md
111
151
  - Rakefile
152
+ - lib/fulfil-io.rb
112
153
  - lib/fulfil.rb
113
154
  - lib/fulfil/client.rb
155
+ - lib/fulfil/error.rb
114
156
  - lib/fulfil/interactive_report.rb
115
157
  - lib/fulfil/model.rb
116
158
  - lib/fulfil/query.rb
159
+ - lib/fulfil/rate_limit.rb
160
+ - lib/fulfil/rate_limit_headers.rb
161
+ - lib/fulfil/response_handler.rb
117
162
  - lib/fulfil/response_parser.rb
118
163
  - lib/fulfil/version.rb
119
164
  homepage: https://github.com/knowndecimal/fulfil
@@ -128,14 +173,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
173
  requirements:
129
174
  - - ">="
130
175
  - !ruby/object:Gem::Version
131
- version: 2.3.0
176
+ version: '2.4'
132
177
  required_rubygems_version: !ruby/object:Gem::Requirement
133
178
  requirements:
134
179
  - - ">="
135
180
  - !ruby/object:Gem::Version
136
181
  version: '0'
137
182
  requirements: []
138
- rubygems_version: 3.1.6
183
+ rubygems_version: 3.3.7
139
184
  signing_key:
140
185
  specification_version: 4
141
186
  summary: Interact with the Fulfil.io API