supergood 0.1.0 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb3307099fe394492d12e7f204da26d9ccb0cca6d53eae8ad1a3e7cc65ae599f
4
- data.tar.gz: 9d8b94b82e04ccdb7d0751b52a29381ebbba02aa2bc7c4e088354626600af5ed
3
+ metadata.gz: a0cdb2377e5748a6ed76d61765fe3b15b648f397a97d6c9cdd28b592d68fd323
4
+ data.tar.gz: '099acaa41f71ef93c745960d9ec046b6643f68501fd95d140a1dd7c62eec76d1'
5
5
  SHA512:
6
- metadata.gz: add414866656373dbef5a3c78bcdf6c0220eda4855bf83c4c0b2ae4a9861e7ad8f071ebe4b3ab80244b74f0646f4953c0fcf8f8c0bba6e8af23a1c34c1c7522f
7
- data.tar.gz: dec173ab5aeb5b18e9cac6a4ef15c00f8b523982b9f313e92e18a42f0c2ab15f568cf6e85662d86843e9166c155a8236afa42dc9d96f2fb25a6635508398bad7
6
+ metadata.gz: 2c15df0347deb5fcb0a0fdf04054595f8c4c9ef8b4da4fabc7879d6098fbe9595c507902ed6f7ccab95b47877f139d9121a1ecea885cb5f814ec86942cb37b3b
7
+ data.tar.gz: 97beed9cd863cd1175756b3084601a40f53928c205b3a3583ca04931a88f6a4804041b8506dfd7277f4232ed1bb7bad3a6eaf5494fe847955dff22439e1882c7
@@ -0,0 +1,26 @@
1
+ name: Unit Tests
2
+ env:
3
+ DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }}
4
+ SUPERGOOD_CLIENT_ID: ${{ secrets.STAGING_SUPERGOOD_CLIENT_ID }}
5
+ SUPERGOOD_CLIENT_SECRET: ${{ secrets.STAGING_SUPERGOOD_CLIENT_SECRET }}
6
+ SUPERGOOD_BASE_URL: 'http://localhost:3000'
7
+ SUPERGOOD_ORGANIZATION_ID: ${{ vars.SUPERGOOD_ORGANIZATION_ID }}
8
+ on:
9
+ push:
10
+ branches:
11
+ - master
12
+ pull_request:
13
+ branches: [master]
14
+ jobs:
15
+ test:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v3
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@359bebbc29cbe6c87da6bc9ea3bc930432750108
21
+ with:
22
+ ruby-version: '3.1'
23
+ - name: Install dependencies
24
+ run: bundle install
25
+ - name: Run tests
26
+ run: bundle exec rspec spec/client_spec.rb
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.2.1
data/Gemfile.lock CHANGED
@@ -1,8 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- supergood (0.0.12)
5
- faraday (~> 2.7, >= 2.7.4)
4
+ supergood (0.1.1)
6
5
  rudash (~> 4.0, >= 4.0.2)
7
6
 
8
7
  GEM
@@ -92,6 +91,7 @@ DEPENDENCIES
92
91
  base64
93
92
  digest
94
93
  dotenv
94
+ faraday (~> 2.7, >= 2.7.4)
95
95
  http (~> 5.1, >= 5.1.1)
96
96
  httparty (~> 0.21.0)
97
97
  json
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # Supergood
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/supergood`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Monitor the cost and performance of your external API's with two lines of code.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Interested in learning more? Check us out at https://supergood.ai or Reach out to alex@supergood.ai .
6
+
7
+ Not built on Ruby? We've got a node client, python client and golang client as well.
6
8
 
7
9
  ## Installation
8
10
 
@@ -22,7 +24,19 @@ Or install it yourself as:
22
24
 
23
25
  ## Usage
24
26
 
25
- TODO: Write usage instructions here
27
+ 1. Head over to https://dashboard.supergood.ai and make an account, make sure to use your work email address!
28
+ 2. Click on the tab labeled "API Keys" and generate a client id and client secret.
29
+ 3. Head back to your code and initialize the Supergood client one of two ways:
30
+
31
+ ```
32
+ require 'supergood'
33
+
34
+ Supergood.init(<client_id>, <client_secret>)
35
+ ```
36
+ OR
37
+
38
+ set `SUPERGOOD_CLIENT_ID` and `SUPERGOOD_CLIENT_SECRET` as environment variables and leave the init function as `Supergood.init`
39
+
26
40
 
27
41
  ## Development
28
42
 
@@ -32,5 +46,5 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
46
 
33
47
  ## Contributing
34
48
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/supergood.
49
+ Bug reports and pull requests are welcome on GitHub at https://github.com/supergoodsystems/supergood-rb.
36
50
 
data/lib/supergood/api.rb CHANGED
@@ -1,13 +1,20 @@
1
- require 'faraday'
2
1
  require 'dotenv'
3
2
 
4
3
  Dotenv.load
5
4
 
6
5
  module Supergood
7
6
  class Api
8
- def initialize(header_options, base_url)
7
+ def initialize(client_id, client_secret, base_url)
9
8
  @base_url = base_url
10
- @header_options = header_options
9
+ @header_options = {
10
+ 'Content-Type' => 'application/json',
11
+ 'Authorization' => 'Basic ' + Base64.encode64(client_id + ':' + client_secret).gsub(/\n/, '')
12
+ }
13
+ @local_only = client_id == LOCAL_CLIENT_ID && client_secret == LOCAL_CLIENT_SECRET
14
+ end
15
+
16
+ def header_options
17
+ @header_options
11
18
  end
12
19
 
13
20
  def log
@@ -18,45 +25,33 @@ module Supergood
18
25
  @log = logger
19
26
  end
20
27
 
21
- def set_event_sink_endpoint(endpoint)
22
- @event_sink_endpoint = endpoint
23
- end
24
-
25
- def set_error_sink_endpoint(endpoint)
26
- @error_sink_endpoint = endpoint
27
- end
28
-
29
28
  def post_events(payload)
30
- conn = Faraday.new(url: @base_url, headers: @header_options)
31
- response = conn.post(@event_sink_endpoint, body = payload.to_json, headers = @header_options)
32
- if response.status == 200
33
- return JSON.parse(response.body, symbolize_names: true)
34
- elsif response.status == 401
35
- raise SupergoodException.new ERRORS[:UNAUTHORIZED]
36
- elsif response.status != 200 && response.status != 201
37
- raise SupergoodException.new ERRORS[:POSTING_EVENTS]
29
+ if @local_only
30
+ @log.debug(payload)
31
+ else
32
+ uri = URI(@base_url + '/api/events')
33
+ response = Net::HTTP.post(uri, payload.to_json, @header_options)
34
+ if response.code == '200'
35
+ return JSON.parse(response.body, symbolize_names: true)
36
+ elsif response.code == '401'
37
+ raise SupergoodException.new ERRORS[:UNAUTHORIZED]
38
+ elsif response.code != '200' && response.code != '201'
39
+ raise SupergoodException.new ERRORS[:POSTING_EVENTS]
40
+ end
38
41
  end
39
42
  end
40
43
 
41
44
  def post_errors(payload)
42
- conn = Faraday.new(url: @base_url, headers: @header_options)
43
- response = conn.post(@error_sink_endpoint, body = payload.to_json, headers = @header_options)
44
- if response.status == 200
45
- return JSON.parse(response.body, symbolize_names: true)
45
+ if @local_only
46
+ @log.debug(payload)
46
47
  else
47
- @log.warn(ERRORS[:POSTING_ERRORS])
48
- end
49
- end
50
-
51
- def fetch_config
52
- conn = Faraday.new(url: @base_url, headers: @header_options)
53
- response = conn.get('/api/config')
54
- if response.status == 200
55
- return JSON.parse(response.body, symbolize_names: true)
56
- elsif response.status == 401
57
- raise SupergoodException.new ERRORS[:UNAUTHORIZED]
58
- elsif response.status != 200 && response.status != 201
59
- raise SupergoodException.new ERRORS[:FETCHING_CONFIG]
48
+ uri = URI(@base_url + '/api/errors')
49
+ response = Net::HTTP.post(uri, payload.to_json, @header_options)
50
+ if response.code == '200'
51
+ return JSON.parse(response.body, symbolize_names: true)
52
+ else
53
+ @log.warn(ERRORS[:POSTING_ERRORS])
54
+ end
60
55
  end
61
56
  end
62
57
  end
@@ -12,11 +12,10 @@ Dotenv.load
12
12
  module Supergood
13
13
 
14
14
  DEFAULT_SUPERGOOD_BASE_URL = 'https://dashboard.supergood.ai'
15
-
16
15
  class << self
17
- def init(supergood_client_id=nil, supergood_client_secret=nil, base_url=nil)
18
- supergood_client_id = supergood_client_id || ENV['SUPERGOOD_CLIENT_ID']
19
- supergood_client_secret = supergood_client_secret || ENV['SUPERGOOD_CLIENT_SECRET']
16
+ def init(config={})
17
+ supergood_client_id = config[:client_id] || ENV['SUPERGOOD_CLIENT_ID']
18
+ supergood_client_secret = config[:client_secret] || ENV['SUPERGOOD_CLIENT_SECRET']
20
19
 
21
20
  if !supergood_client_id
22
21
  raise SupergoodException.new ERRORS[:NO_CLIENT_ID]
@@ -26,27 +25,27 @@ module Supergood
26
25
  raise SupergoodException.new ERRORS[:NO_CLIENT_SECRET]
27
26
  end
28
27
 
29
- @base_url = base_url || ENV['SUPERGOOD_BASE_URL'] || DEFAULT_SUPERGOOD_BASE_URL
30
- header_options = {
31
- 'Content-Type' => 'application/json',
32
- 'Authorization' => 'Basic ' + Base64.encode64(supergood_client_id + ':' + supergood_client_secret).gsub(/\n/, '')
33
- }
28
+ @base_url = ENV['SUPERGOOD_BASE_URL'] || DEFAULT_SUPERGOOD_BASE_URL
29
+ @api = Supergood::Api.new(supergood_client_id, supergood_client_secret, @base_url)
30
+ @config = Supergood::Utils.make_config(config)
34
31
 
35
- @api = Supergood::Api.new(header_options, @base_url)
36
- @config = @api.fetch_config
37
32
  @ignored_domains = @config[:ignoredDomains]
38
33
  @keys_to_hash = @config[:keysToHash]
39
- @logger = Supergood::Logger.new(@api, @config, header_options)
34
+ @logger = Supergood::Logger.new(@api, @config, @api.header_options)
40
35
 
41
- @api.set_error_sink_endpoint(@config[:errorSinkEndpoint])
42
- @api.set_event_sink_endpoint(@config[:eventSinkEndpoint])
43
36
  @api.set_logger(@logger)
44
37
 
45
38
  @request_cache = {}
46
39
  @response_cache = {}
47
40
 
48
41
  @interval_thread = set_interval(@config[:flushInterval]) { flush_cache }
49
- log.debug("Using config %s" % @config.inspect)
42
+
43
+ @http_clients = [
44
+ Supergood::Vendor::NetHTTP,
45
+ Supergood::Vendor::HTTPrb
46
+ ]
47
+
48
+ patch_all()
50
49
  self
51
50
  end
52
51
 
@@ -76,6 +75,7 @@ module Supergood
76
75
  api.post_events(data)
77
76
  rescue => e
78
77
  log.error(data, e, e.message)
78
+ cleanup()
79
79
  ensure
80
80
  @response_cache.clear
81
81
  @request_cache.clear if force
@@ -83,10 +83,27 @@ module Supergood
83
83
 
84
84
  end
85
85
 
86
+ def cleanup()
87
+ @interval_thread.kill
88
+ unpatch_all()
89
+ end
90
+
86
91
  def close(force = true)
87
92
  log.debug('Cleaning up, flushing cache gracefully.')
88
- @interval_thread.kill
89
93
  flush_cache(force)
94
+ cleanup()
95
+ end
96
+
97
+ def patch_all
98
+ @http_clients.each do |client|
99
+ client.patch
100
+ end
101
+ end
102
+
103
+ def unpatch_all
104
+ @http_clients.each do |client|
105
+ client.unpatch
106
+ end
90
107
  end
91
108
 
92
109
  def set_interval(delay)
@@ -98,14 +115,6 @@ module Supergood
98
115
  end
99
116
  end
100
117
 
101
- def self.intercept(*args, &block)
102
- instance.intercept(*args, &block)
103
- end
104
-
105
- def self.instance
106
- @instance ||= Supergood.new
107
- end
108
-
109
118
  def intercept(request)
110
119
  request_id = SecureRandom.uuid
111
120
  requested_at = Time.now
@@ -138,6 +147,7 @@ module Supergood
138
147
  }
139
148
  rescue => e
140
149
  log.error({ request: request }, e, ERRORS[:CACHING_REQUEST])
150
+ cleanup()
141
151
  end
142
152
  end
143
153
 
@@ -159,11 +169,11 @@ module Supergood
159
169
  }), @keys_to_hash)
160
170
  @request_cache.delete(request_id)
161
171
  rescue => e
162
- puts e
163
172
  log.error(
164
173
  { request: request_payload, response: response_payload },
165
174
  e, ERRORS[:CACHING_RESPONSE]
166
175
  )
176
+ cleanup()
167
177
  end
168
178
  end
169
179
 
@@ -4,9 +4,8 @@ ERRORS = {
4
4
  DUMPING_DATA_TO_DISK: 'Error Dumping Data to Disk',
5
5
  POSTING_EVENTS: 'Error Posting Events',
6
6
  POSTING_ERRORS: 'Error Posting Errors',
7
- FETCHING_CONFIG: 'Error Fetching Config',
8
7
  WRITING_TO_DISK: 'Error writing to disk',
9
- TEST_ERROR: 'Test Error for Testing Purposes',
8
+ TEST_ERROR: 'Test Error for Testing Purpos es',
10
9
  UNAUTHORIZED: 'Unauthorized: Invalid Client ID or Secret. Exiting.',
11
10
  NO_CLIENT_ID:
12
11
  'No Client ID Provided, set SUPERGOOD_CLIENT_ID or pass it as an argument',
@@ -14,8 +13,17 @@ ERRORS = {
14
13
  'No Client Secret Provided, set SUPERGOOD_CLIENT_SECRET or pass it as an argument'
15
14
  };
16
15
 
16
+ LOCAL_CLIENT_ID = 'local-client-id';
17
+ LOCAL_CLIENT_SECRET = 'local-client-secret';
18
+
17
19
  DEFAULT_SUPERGOOD_BYTE_LIMIT = 500000
18
20
 
21
+ DEFAULT_CONFIG = {
22
+ keysToHash: [],
23
+ flushInterval: 1000,
24
+ ignoredDomains: []
25
+ }
26
+
19
27
  # GZIP_START_BYTES = b'\x1f\x8b'
20
28
 
21
29
  class SupergoodException < StandardError
@@ -68,5 +68,9 @@ module Supergood
68
68
  def self.request_url(http, request)
69
69
  URI::DEFAULT_PARSER.unescape("http#{"s" if http.use_ssl?}://#{http.address}#{request.path}")
70
70
  end
71
+
72
+ def self.make_config(config)
73
+ return DEFAULT_CONFIG.merge(config)
74
+ end
71
75
  end
72
76
  end
@@ -1,33 +1,59 @@
1
1
  module Supergood
2
2
  module Vendor
3
3
  module HTTPrb
4
- if defined?(HTTP::Client)
5
- HTTP::Client.class_eval {
6
- alias original_perform perform
7
- def perform(original_request_payload, original_options)
8
- request = {
9
- headers: original_request_payload.headers.to_hash,
10
- method: original_request_payload.verb.upcase.to_s,
11
- body: Supergood::Utils.safe_parse_json(original_request_payload.body.source),
12
- url: original_request_payload.uri.to_s,
13
- path: original_request_payload.uri.path,
14
- search: original_request_payload.uri.query,
15
- domain: original_request_payload.uri.host
16
- }
17
- Supergood.intercept(request) do
18
- original_response = original_perform(original_request_payload, original_options)
19
- status, statusText = original_response.status.to_s.split(' ')
20
- {
21
- headers: original_response.headers.to_hash,
22
- status: status,
23
- statusText: statusText,
24
- body: Supergood::Utils.safe_parse_json(original_response),
25
- original_response: original_response
4
+ def self.patch
5
+ if !self.existing_patch?
6
+
7
+ block = lambda do |x|
8
+ alias original_perform perform
9
+ def perform(original_request_payload, original_options)
10
+ request = {
11
+ headers: original_request_payload.headers.to_hash,
12
+ method: original_request_payload.verb.upcase.to_s,
13
+ body: Supergood::Utils.safe_parse_json(original_request_payload.body.source),
14
+ url: original_request_payload.uri.to_s,
15
+ path: original_request_payload.uri.path,
16
+ search: original_request_payload.uri.query,
17
+ domain: original_request_payload.uri.host
26
18
  }
19
+ Supergood.intercept(request) do
20
+ original_response = original_perform(original_request_payload, original_options)
21
+ status, statusText = original_response.status.to_s.split(' ')
22
+ {
23
+ headers: original_response.headers.to_hash,
24
+ status: status,
25
+ statusText: statusText,
26
+ body: Supergood::Utils.safe_parse_json(original_response),
27
+ original_response: original_response
28
+ }
29
+ end
27
30
  end
28
31
  end
29
- }
32
+
33
+ if defined?(HTTP::Client)
34
+ HTTP::Client.class_eval(&block)
35
+ end
36
+
37
+ end
38
+ end
39
+
40
+ def self.unpatch
41
+ if self.existing_patch?
42
+ block = lambda do |x|
43
+ alias perform original_perform
44
+ end
45
+
46
+ if defined?(HTTP::Client)
47
+ HTTP::Client.class_eval(&block)
48
+ HTTP::Client.undef_method :original_perform
49
+ end
50
+ end
30
51
  end
52
+
53
+ def self.existing_patch?
54
+ defined?(HTTP::Client) && HTTP::Client.method_defined?(:original_perform)
55
+ end
56
+
31
57
  end
32
58
  end
33
59
  end
@@ -5,41 +5,66 @@ require 'uri'
5
5
  module Supergood
6
6
  module Vendor
7
7
  module NetHTTP
8
- block = lambda do |x|
9
- alias original_request_method request
10
- def request(original_request_payload, body = nil, &block)
11
- http = self;
12
- url = Supergood::Utils.request_url(http, original_request_payload)
13
- uri = URI.parse(url)
14
- request = {
15
- headers: Supergood::Utils.get_header(original_request_payload),
16
- method: original_request_payload.method,
17
- body: original_request_payload.body,
18
- url: url,
19
- path: original_request_payload.path,
20
- search: uri.query,
21
- domain: uri.host,
22
- }
23
- Supergood.intercept(request) do
24
- original_response = original_request_method(original_request_payload, body, &block)
25
- {
26
- headers: Supergood::Utils.get_header(original_response),
27
- status: original_response.code,
28
- statusText: original_response.message,
29
- body: original_response.body,
30
- original_response: original_response
31
- }
8
+ def self.patch
9
+ if !self.existing_patch?
10
+ block = lambda do |x|
11
+ alias original_request_method request
12
+ def request(original_request_payload, body = nil, &block)
13
+ http = self;
14
+ url = Supergood::Utils.request_url(http, original_request_payload)
15
+ uri = URI.parse(url)
16
+ request = {
17
+ headers: Supergood::Utils.get_header(original_request_payload),
18
+ method: original_request_payload.method,
19
+ body: original_request_payload.body,
20
+ url: url,
21
+ path: original_request_payload.path,
22
+ search: uri.query,
23
+ domain: uri.host,
24
+ }
25
+ Supergood.intercept(request) do
26
+ original_response = original_request_method(original_request_payload, body, &block)
27
+ {
28
+ headers: Supergood::Utils.get_header(original_response),
29
+ status: original_response.code,
30
+ statusText: original_response.message,
31
+ body: original_response.body,
32
+ original_response: original_response
33
+ }
34
+ end
35
+ end
32
36
  end
37
+
38
+ if defined?(Net::HTTP)
39
+ Net::HTTP.class_eval(&block)
40
+ elsif defined?(::WebMock)
41
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").class_eval(&block)
42
+ end
43
+
33
44
  end
34
45
  end
35
46
 
36
- if defined?(Net::HTTP)
37
- Net::HTTP.class_eval(&block)
47
+ def self.unpatch
48
+ if self.existing_patch?
49
+ block = lambda do |x|
50
+ alias request original_request_method
51
+ end
52
+
53
+ if defined?(Net::HTTP)
54
+ Net::HTTP.class_eval(&block)
55
+ Net::HTTP.undef_method :original_request_method
56
+ elsif defined?(::WebMock)
57
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").class_eval(&block)
58
+ WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").undef_method :original_request_method
59
+ end
60
+ end
38
61
  end
39
62
 
40
- if defined?(::WebMock)
41
- WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").class_eval(&block)
63
+ def self.existing_patch?
64
+ (defined?(Net::HTTP) && Net::HTTP.method_defined?(:original_request_method)) ||
65
+ (defined?(::Webmock) && WebMock::HttpLibAdapters::NetHttpAdapter.instance_variable_get("@webMockNetHTTP").method_defined?(:original_request_method))
42
66
  end
67
+
43
68
  end
44
69
  end
45
70
  end
@@ -1,3 +1,3 @@
1
1
  module Supergood
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.1.2'.freeze
3
3
  end
data/supergood.gemspec CHANGED
@@ -19,13 +19,13 @@ Gem::Specification.new do |s|
19
19
  s.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
20
20
 
21
21
  s.add_dependency 'rudash', '~> 4.0', '>= 4.0.2'
22
- s.add_dependency 'faraday', '~> 2.7', '>= 2.7.4'
23
22
 
24
23
  s.add_development_dependency 'rest-client', '~> 2.1'
25
24
  s.add_development_dependency 'httparty', '~> 0.21.0'
26
25
  s.add_development_dependency 'http', '~> 5.1', '>= 5.1.1'
27
26
  s.add_development_dependency 'rspec', '~> 3.12'
28
27
  s.add_development_dependency 'webmock', '~> 3.18', '>= 3.18.1'
28
+ s.add_development_dependency 'faraday', '~> 2.7', '>= 2.7.4'
29
29
 
30
30
  end
31
31
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: supergood
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Klarfeld
@@ -30,26 +30,6 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 4.0.2
33
- - !ruby/object:Gem::Dependency
34
- name: faraday
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2.7'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 2.7.4
43
- type: :runtime
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - "~>"
48
- - !ruby/object:Gem::Version
49
- version: '2.7'
50
- - - ">="
51
- - !ruby/object:Gem::Version
52
- version: 2.7.4
53
33
  - !ruby/object:Gem::Dependency
54
34
  name: rest-client
55
35
  requirement: !ruby/object:Gem::Requirement
@@ -132,14 +112,36 @@ dependencies:
132
112
  - - ">="
133
113
  - !ruby/object:Gem::Version
134
114
  version: 3.18.1
115
+ - !ruby/object:Gem::Dependency
116
+ name: faraday
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '2.7'
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 2.7.4
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2.7'
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 2.7.4
135
135
  description:
136
136
  email: alex@supergood.ai
137
137
  executables: []
138
138
  extensions: []
139
139
  extra_rdoc_files: []
140
140
  files:
141
+ - ".github/workflows/test.yml"
141
142
  - ".gitignore"
142
143
  - ".rspec"
144
+ - ".tool-versions"
143
145
  - ".travis.yml"
144
146
  - ".vscode/settings.json"
145
147
  - Gemfile