pluton8 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +10 -0
- data/app/assets/config/api_base_manifest.js +1 -0
- data/app/assets/stylesheets/api_base/application.css +15 -0
- data/app/controllers/api_base/application_controller.rb +6 -0
- data/app/helpers/api_base/application_helper.rb +6 -0
- data/app/jobs/api_base/application_job.rb +6 -0
- data/app/mailers/api_base/application_mailer.rb +8 -0
- data/app/models/api_base/api_log.rb +108 -0
- data/app/models/api_base/application_record.rb +7 -0
- data/app/views/layouts/api_base/application.html.erb +15 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20220612165032_create_api_logs.rb +22 -0
- data/lib/api_base/behaviours/get_json.rb +26 -0
- data/lib/api_base/behaviours/post_json.rb +27 -0
- data/lib/api_base/behaviours/shared.rb +51 -0
- data/lib/api_base/concerns/filterer.rb +47 -0
- data/lib/api_base/concerns/traceable.rb +25 -0
- data/lib/api_base/connection.rb +24 -0
- data/lib/api_base/endpoint.rb +65 -0
- data/lib/api_base/engine.rb +7 -0
- data/lib/api_base/errors/api_error.rb +8 -0
- data/lib/api_base/errors/processing_error.rb +8 -0
- data/lib/api_base/service.rb +17 -0
- data/lib/api_base/version.rb +5 -0
- data/lib/api_base.rb +14 -0
- data/lib/tasks/api_base_tasks.rake +5 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: deb82287262c2b97f12fd5bfc979f4a941298cd65e49e54a9a5230589e51d0ce
|
4
|
+
data.tar.gz: 323132fc5bc08c80d53a3777fa394b1807c90b24d47cb3ee423d2dc699f8b644
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 418ba9c52c8bb793796d9b1dd7bdf49bd535475ef091acdbfa21e5616373f7523c61a957c13bd4b3ab0a0f9ac69f1129c6b78b5e9f4fa9b3222b5e9a3bf1cf3c
|
7
|
+
data.tar.gz: 1c9ba047239d839c8c7af40fa9b804d877af7c075e8920901ba1422acff6d4de9c65211a00c8d5909e511f7d0ee520341de58038acb33a24e3ee4c93b5facf49
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Stefan Froelich
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# ApiBase
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "api_base"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install api_base
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/api_base .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: api_logs
|
6
|
+
#
|
7
|
+
# id :bigint not null, primary key
|
8
|
+
# api :text not null
|
9
|
+
# duration :float
|
10
|
+
# endpoint :text not null
|
11
|
+
# exception :jsonb
|
12
|
+
# method :text not null
|
13
|
+
# origin :text not null
|
14
|
+
# request_body :jsonb
|
15
|
+
# request_headers :jsonb
|
16
|
+
# response_body :jsonb
|
17
|
+
# response_headers :jsonb
|
18
|
+
# source :text not null
|
19
|
+
# status_code :integer
|
20
|
+
# created_at :datetime not null
|
21
|
+
# updated_at :datetime not null
|
22
|
+
#
|
23
|
+
require 'English'
|
24
|
+
|
25
|
+
module ApiBase
|
26
|
+
class ApiLog < ApplicationRecord
|
27
|
+
attribute :sanitized, :boolean, default: false
|
28
|
+
|
29
|
+
validate :ensure_nothing_changed, unless: :new_record?
|
30
|
+
validate :ensure_data_sanitized
|
31
|
+
|
32
|
+
validates_presence_of :api, :origin, :source, :endpoint
|
33
|
+
|
34
|
+
validates :source, presence: true, inclusion: { in: %w[outgoing_request incoming_webhook] }
|
35
|
+
validates :method, presence: true, inclusion: { in: %w[GET POST DELETE PUT] }
|
36
|
+
|
37
|
+
def self.start_outgoing_request(origin, method, endpoint, payload)
|
38
|
+
ApiLog.new api: origin.identifier, origin: origin.class.to_s, source: 'outgoing_request',
|
39
|
+
endpoint: "#{origin.connection.url_prefix}#{endpoint}", method:,
|
40
|
+
request_headers: origin.connection.headers, request_body: payload
|
41
|
+
end
|
42
|
+
|
43
|
+
def complete_outgoing_request(response, duration)
|
44
|
+
# Ensure we are recording the actual headers that were sent on the request.
|
45
|
+
# The ones set from the connection might not be the final headers.
|
46
|
+
self.request_headers = response.env.request_headers
|
47
|
+
# Set the rest of the response attributes.
|
48
|
+
assign_attributes status_code: response.status, duration:,
|
49
|
+
response_body: response.body, response_headers: response.headers
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.start_webhook_request(origin, request)
|
53
|
+
ApiLog.new api: origin, origin: origin.class.to_s, source: 'incoming_webhook',
|
54
|
+
endpoint: request.fullpath, method: request.method,
|
55
|
+
request_headers: request.headers.env.reject { |key|
|
56
|
+
key.to_s.include?('.')
|
57
|
+
}, request_body: request.params
|
58
|
+
end
|
59
|
+
|
60
|
+
def complete_webhook_request(response, duration)
|
61
|
+
# Set the rest of the response attributes.
|
62
|
+
assign_attributes status_code: response.status, duration:,
|
63
|
+
response_body: response.body, response_headers: response.headers
|
64
|
+
end
|
65
|
+
|
66
|
+
def filter_sensitive_data
|
67
|
+
parse_json_fields
|
68
|
+
|
69
|
+
%i[request_headers request_body response_headers response_body exception].each do |prop|
|
70
|
+
self[prop] = yield(self[prop]) if self[prop].is_a?(Hash)
|
71
|
+
end
|
72
|
+
|
73
|
+
self.sanitized = true
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def ensure_nothing_changed
|
79
|
+
errors.add(:base, 'Record is read-only') if changed?
|
80
|
+
end
|
81
|
+
|
82
|
+
def ensure_data_sanitized
|
83
|
+
errors.add(:base, 'Data must be sanitized') unless sanitized?
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_json_fields
|
87
|
+
%i[request_headers request_body response_headers response_body exception].each do |prop|
|
88
|
+
self[prop] = safely_parse_json(self[prop])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def safely_parse_json(value)
|
93
|
+
case value
|
94
|
+
when nil, Hash
|
95
|
+
value
|
96
|
+
when String
|
97
|
+
JSON.parse value
|
98
|
+
when StandardError
|
99
|
+
[e.message, *e.backtrace].join($INPUT_RECORD_SEPARATOR).to_json
|
100
|
+
else
|
101
|
+
value.to_s.to_json
|
102
|
+
end
|
103
|
+
rescue StandardError
|
104
|
+
# Something we can't encode. Let's preserve it as a string.
|
105
|
+
value.to_s.to_json
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateApiLogs < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :api_base_api_logs do |t|
|
6
|
+
t.text :api, null: false
|
7
|
+
t.text :origin, null: false
|
8
|
+
t.text :source, null: false
|
9
|
+
t.text :endpoint, null: false
|
10
|
+
t.text :method, null: false
|
11
|
+
t.jsonb :request_headers
|
12
|
+
t.jsonb :request_body
|
13
|
+
t.integer :status_code
|
14
|
+
t.jsonb :response_headers
|
15
|
+
t.jsonb :response_body
|
16
|
+
t.float :duration
|
17
|
+
t.jsonb :exception
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Behaviours
|
5
|
+
# Shared concern that adds the ability to get json from an endpoint
|
6
|
+
module GetJson
|
7
|
+
include Shared
|
8
|
+
|
9
|
+
alias get_json behaviour_delegate
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def execute_request(endpoint, _payload)
|
14
|
+
execute do
|
15
|
+
connection.get(endpoint) do |req|
|
16
|
+
req.headers['Content-Type'] = 'application/json'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def method
|
22
|
+
'GET'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Behaviours
|
5
|
+
# Shared concern that adds the ability to post json to an endpoint
|
6
|
+
module PostJson
|
7
|
+
include Shared
|
8
|
+
|
9
|
+
alias post_json behaviour_delegate
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def execute_request(endpoint, payload)
|
14
|
+
execute do
|
15
|
+
connection.post(endpoint, payload) do |req|
|
16
|
+
req.body = payload.to_json
|
17
|
+
req.headers['Content-Type'] = 'application/json'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def method
|
23
|
+
'POST'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Behaviours
|
5
|
+
# Shared module that adds common methods to api behaviours
|
6
|
+
module Shared
|
7
|
+
def behaviour_delegate(endpoint, payload = {})
|
8
|
+
api_log = ApiBase::ApiLog.start_outgoing_request(self, method, endpoint, payload)
|
9
|
+
response, duration = make_request(endpoint, payload)
|
10
|
+
api_log.complete_outgoing_request response, duration
|
11
|
+
|
12
|
+
response
|
13
|
+
rescue StandardError => e
|
14
|
+
api_log.exception = e if api_log.present?
|
15
|
+
raise
|
16
|
+
ensure
|
17
|
+
if api_log.present?
|
18
|
+
api_log.filter_sensitive_data { |data| filter_object(data) }
|
19
|
+
api_log.save!
|
20
|
+
end
|
21
|
+
|
22
|
+
validate_status_code response if response.present?
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def make_request(endpoint, payload)
|
28
|
+
trace_active_tag('request.endpoint', endpoint)
|
29
|
+
trace_active_tag('request.payload', filter_object(payload))
|
30
|
+
|
31
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
32
|
+
response = execute_request(endpoint, payload)
|
33
|
+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
34
|
+
|
35
|
+
trace_active_tag('response.status', response.status)
|
36
|
+
trace_active_tag('response.body', filter_object(response.body))
|
37
|
+
trace_active_tag('response.duration', duration)
|
38
|
+
|
39
|
+
[response, duration]
|
40
|
+
end
|
41
|
+
|
42
|
+
def method
|
43
|
+
raise NotImplementedError, 'method is not implemented'
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute_request
|
47
|
+
raise NotImplementedError, 'execute_request is not implemented'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Concerns
|
5
|
+
module Filterer
|
6
|
+
protected
|
7
|
+
|
8
|
+
def filterer
|
9
|
+
@filterer ||= ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
|
10
|
+
end
|
11
|
+
|
12
|
+
def filter_object(obj)
|
13
|
+
return if obj.nil?
|
14
|
+
|
15
|
+
case obj
|
16
|
+
when Array then filter_array(obj)
|
17
|
+
when Hash then filter_hash(obj)
|
18
|
+
else obj
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def filter_array(array)
|
23
|
+
return if array.nil?
|
24
|
+
|
25
|
+
array.map do |item|
|
26
|
+
case item
|
27
|
+
when Array then filter_array(item)
|
28
|
+
when Hash then filter_hash(item)
|
29
|
+
else item
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def filter_hash(hash)
|
35
|
+
return if hash.nil?
|
36
|
+
|
37
|
+
hash.each do |key, value|
|
38
|
+
case value
|
39
|
+
when Array then hash[key] = filter_array(value)
|
40
|
+
when Hash then hash[key] = filter_hash(value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
filterer.filter (hash.try(:permit!) || hash).to_hash
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Concerns
|
5
|
+
module Traceable
|
6
|
+
protected
|
7
|
+
|
8
|
+
def trace_root_tag(name, value)
|
9
|
+
Rails.logger.debug "trace_root_tag -> #{name} | #{value}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def trace_root_error(error)
|
13
|
+
Rails.logger.debug "trace_root_error -> #{error}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def trace_active_tag(name, value)
|
17
|
+
Rails.logger.debug "trace_active_tag -> #{name} | #{value}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def trace_active_error(error)
|
21
|
+
Rails.logger.debug "trace_active_error -> #{error}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Connection
|
5
|
+
def connection
|
6
|
+
@connection_cache ||= {}
|
7
|
+
@connection_cache[connection_name] ||= with_connection(connection_name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def connection_name
|
11
|
+
defined?(@connection_name) ? @connection_name.to_sym : :default
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_connection(connection_name)
|
15
|
+
@connection_name = connection_name
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def with_connection(connection_name)
|
21
|
+
raise NotImplementedError, "with_connection is not implemented"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'stoplight'
|
5
|
+
require 'api_base/service'
|
6
|
+
require 'api_base/connection'
|
7
|
+
require 'api_base/concerns/traceable'
|
8
|
+
require 'api_base/concerns/filterer'
|
9
|
+
require 'api_base/errors/api_error'
|
10
|
+
require 'api_base/errors/processing_error'
|
11
|
+
|
12
|
+
module ApiBase
|
13
|
+
class Endpoint
|
14
|
+
include ActiveSupport::Rescuable
|
15
|
+
include Concerns::Traceable
|
16
|
+
include Concerns::Filterer
|
17
|
+
include ApiBase::Service
|
18
|
+
include ApiBase::Connection
|
19
|
+
|
20
|
+
rescue_from Stoplight::Error::RedLight do
|
21
|
+
Rails.logger.warn "#{identifier} api circuit is closed"
|
22
|
+
raise ApiBase::Errors::ApiError, 'Circuit broken'
|
23
|
+
end
|
24
|
+
|
25
|
+
rescue_from Faraday::TimeoutError do
|
26
|
+
Rails.logger.warn "#{identifier} api timed-out"
|
27
|
+
raise ApiBase::Errors::ApiError, 'Request timed-out'
|
28
|
+
end
|
29
|
+
|
30
|
+
def identifier
|
31
|
+
"#{service_name}:#{connection_name}"
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def execute(&block)
|
37
|
+
light = Stoplight(identifier) do
|
38
|
+
block.call
|
39
|
+
end
|
40
|
+
|
41
|
+
light.with_error_handler do |error, handler|
|
42
|
+
# We don't want processing errors to affect our circuit breakers
|
43
|
+
# They are our api equivalent of runtime errors.
|
44
|
+
raise error if error.is_a?(ApiBase::Errors::ProcessingError)
|
45
|
+
|
46
|
+
handler.call(error)
|
47
|
+
end
|
48
|
+
|
49
|
+
light.run
|
50
|
+
rescue StandardError => e
|
51
|
+
trace_active_error(e)
|
52
|
+
rescue_with_handler(e) || raise
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_status_code(response)
|
56
|
+
return if success_status_codes.include?(response.status)
|
57
|
+
|
58
|
+
raise ApiBase::Errors::ProcessingError, "Request failed with status: #{response.status}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def filterer
|
62
|
+
@filterer ||= ActiveSupport::ParameterFilter.new sensitive_keys
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ApiBase
|
4
|
+
module Service
|
5
|
+
def service_name
|
6
|
+
raise NotImplementedError, 'service_name is not implemented'
|
7
|
+
end
|
8
|
+
|
9
|
+
def sensitive_keys
|
10
|
+
raise NotImplementedError, 'sensitive_keys is not implemented'
|
11
|
+
end
|
12
|
+
|
13
|
+
def success_status_codes
|
14
|
+
[200, 201]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/api_base.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'api_base/version'
|
4
|
+
require 'api_base/engine'
|
5
|
+
require 'api_base/endpoint'
|
6
|
+
require 'api_base/behaviours/shared'
|
7
|
+
require 'api_base/behaviours/get_json'
|
8
|
+
require 'api_base/behaviours/post_json'
|
9
|
+
require 'api_base/errors/api_error'
|
10
|
+
require 'api_base/errors/processing_error'
|
11
|
+
|
12
|
+
module ApiBase
|
13
|
+
# Your code goes here...
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pluton8
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stefan Froelich
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 6.0.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 6.0.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: stoplight
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
55
|
+
description: Building blocks for building API Clients
|
56
|
+
email:
|
57
|
+
- sfroelich01@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- app/assets/config/api_base_manifest.js
|
66
|
+
- app/assets/stylesheets/api_base/application.css
|
67
|
+
- app/controllers/api_base/application_controller.rb
|
68
|
+
- app/helpers/api_base/application_helper.rb
|
69
|
+
- app/jobs/api_base/application_job.rb
|
70
|
+
- app/mailers/api_base/application_mailer.rb
|
71
|
+
- app/models/api_base/api_log.rb
|
72
|
+
- app/models/api_base/application_record.rb
|
73
|
+
- app/views/layouts/api_base/application.html.erb
|
74
|
+
- config/routes.rb
|
75
|
+
- db/migrate/20220612165032_create_api_logs.rb
|
76
|
+
- lib/api_base.rb
|
77
|
+
- lib/api_base/behaviours/get_json.rb
|
78
|
+
- lib/api_base/behaviours/post_json.rb
|
79
|
+
- lib/api_base/behaviours/shared.rb
|
80
|
+
- lib/api_base/concerns/filterer.rb
|
81
|
+
- lib/api_base/concerns/traceable.rb
|
82
|
+
- lib/api_base/connection.rb
|
83
|
+
- lib/api_base/endpoint.rb
|
84
|
+
- lib/api_base/engine.rb
|
85
|
+
- lib/api_base/errors/api_error.rb
|
86
|
+
- lib/api_base/errors/processing_error.rb
|
87
|
+
- lib/api_base/service.rb
|
88
|
+
- lib/api_base/version.rb
|
89
|
+
- lib/tasks/api_base_tasks.rake
|
90
|
+
homepage: https://github.com/ussd-engine/api-base
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata:
|
94
|
+
allowed_push_host: https://rubygems.org
|
95
|
+
homepage_uri: https://github.com/ussd-engine/api-base
|
96
|
+
source_code_uri: https://github.com/ussd-engine/api-base
|
97
|
+
changelog_uri: https://github.com/ussd-engine/api-base
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubygems_version: 3.3.7
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Building blocks for building API Clients
|
117
|
+
test_files: []
|