shaf_client 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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/shaf_client.rb +87 -0
- data/lib/shaf_client/base_resource.rb +118 -0
- data/lib/shaf_client/curie.rb +25 -0
- data/lib/shaf_client/form.rb +37 -0
- data/lib/shaf_client/link.rb +42 -0
- data/lib/shaf_client/middleware/cache.rb +181 -0
- data/lib/shaf_client/resource.rb +39 -0
- metadata +86 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6522a9d02450366d188195b580b2880a643cd596d284e6ada3d13228160b0038
|
4
|
+
data.tar.gz: 3aa9f908ed8f9e7b3ce423c27fcd640bd4569cdbf1e533d64c67d76dd8da5962
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 775eb0e67adf697b7213a407cf836a829ba2f73555cbb68b234ad94461a37966e4a278c7738259b0e9b127c40aacdc2cbae6adfa56d697655282c7d1c28b3cbf
|
7
|
+
data.tar.gz: c1cc2969026ab53b58d12a5c5404922afffa89f1be47a08f4b92eb0c3d9bd9d9e190265bd690a0939bcee1ca8dca9926884ecc88f99b625280f5104a13960ff7
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
Binary file
|
data/lib/shaf_client.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
require 'shaf_client/middleware/cache'
|
4
|
+
require 'shaf_client/resource'
|
5
|
+
require 'shaf_client/form'
|
6
|
+
|
7
|
+
class ShafClient
|
8
|
+
extend Middleware::Cache::Control
|
9
|
+
|
10
|
+
MIME_TYPE_JSON = 'application/json'
|
11
|
+
|
12
|
+
def initialize(root_uri, **options)
|
13
|
+
@root_uri = root_uri.dup
|
14
|
+
adapter = options.fetch(:faraday_adapter, :net_http)
|
15
|
+
setup options
|
16
|
+
|
17
|
+
@client = Faraday.new(url: root_uri) do |conn|
|
18
|
+
conn.basic_auth(@user, @pass) if basic_auth?
|
19
|
+
conn.use Middleware::Cache, auth_header: auth_header
|
20
|
+
conn.adapter adapter
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_root
|
25
|
+
get(@root_uri)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_form(uri)
|
29
|
+
response = request(method: :get, uri: uri)
|
30
|
+
Form.new(self, response.body)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_doc(uri)
|
34
|
+
response = request(method: :get, uri: uri)
|
35
|
+
response&.body || ''
|
36
|
+
end
|
37
|
+
|
38
|
+
%i[get put post delete patch].each do |method|
|
39
|
+
define_method(method) do |uri, payload = nil|
|
40
|
+
with_resource do
|
41
|
+
request(method: method, uri: uri, payload: payload)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :auth_header
|
49
|
+
|
50
|
+
def setup(options)
|
51
|
+
setup_default_headers options
|
52
|
+
setup_basic_auth options
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_default_headers(options)
|
56
|
+
@default_headers = {
|
57
|
+
'Content-Type' => options.fetch(:content_type, MIME_TYPE_JSON)
|
58
|
+
}
|
59
|
+
return unless token = options[:auth_token]
|
60
|
+
|
61
|
+
@auth_header = options.fetch(:auth_header, 'X-Auth-Token')
|
62
|
+
@default_headers[@auth_header] = token
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup_basic_auth(options)
|
66
|
+
@user, @pass = options.slice(:user, :password).values
|
67
|
+
@auth_header = options.fetch(:auth_header, 'Authorization') if basic_auth?
|
68
|
+
end
|
69
|
+
|
70
|
+
def basic_auth?
|
71
|
+
@user && @pass
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_resource
|
75
|
+
response = yield
|
76
|
+
Resource.new(self, response.body)
|
77
|
+
end
|
78
|
+
|
79
|
+
def request(method:, uri:, payload: nil, headers: {})
|
80
|
+
payload = JSON.generate(payload) if payload&.is_a?(Hash)
|
81
|
+
@client.send(method) do |req|
|
82
|
+
req.url uri
|
83
|
+
req.body = payload if payload
|
84
|
+
req.headers.merge! @default_headers.merge(headers)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'shaf_client/link'
|
3
|
+
require 'shaf_client/curie'
|
4
|
+
|
5
|
+
class ShafClient
|
6
|
+
class BaseResource
|
7
|
+
attr_reader :attributes, :links, :curies, :embedded_resources
|
8
|
+
|
9
|
+
def initialize(payload)
|
10
|
+
@payload =
|
11
|
+
if payload&.is_a? String
|
12
|
+
JSON.parse(payload)
|
13
|
+
else
|
14
|
+
payload
|
15
|
+
end
|
16
|
+
|
17
|
+
parse
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
attributes
|
22
|
+
.merge(_links: transform_values_to_s(links))
|
23
|
+
.merge(_embedded: transform_values_to_s(embedded_resources))
|
24
|
+
.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def attribute(key)
|
28
|
+
attributes.fetch(key.to_sym)
|
29
|
+
end
|
30
|
+
|
31
|
+
def link(rel)
|
32
|
+
links.fetch(rel.to_sym)
|
33
|
+
end
|
34
|
+
|
35
|
+
def curie(rel)
|
36
|
+
curies.fetch(rel.to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def embedded(rel)
|
40
|
+
embedded_resources.fetch(rel.to_sym)
|
41
|
+
end
|
42
|
+
|
43
|
+
def [](key)
|
44
|
+
attributes[key]
|
45
|
+
end
|
46
|
+
|
47
|
+
def actions
|
48
|
+
links.keys
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def payload
|
54
|
+
@payload ||= {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse
|
58
|
+
@attributes = payload.transform_keys(&:to_sym)
|
59
|
+
parse_links
|
60
|
+
parse_embedded
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_links
|
64
|
+
links = attributes.delete(:_links) || {}
|
65
|
+
@links ||= {}
|
66
|
+
@curies ||= {}
|
67
|
+
|
68
|
+
links.each do |key, value|
|
69
|
+
next parse_curies(value) if key == 'curies'
|
70
|
+
@links[key.to_sym] = Link.from(value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_curies(curies)
|
75
|
+
curies.each do |value|
|
76
|
+
curie = Curie.from(value)
|
77
|
+
@curies[curie.name.to_sym] = curie
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_embedded
|
82
|
+
embedded = @attributes.delete(:_embedded) || {}
|
83
|
+
@embedded_resources ||= {}
|
84
|
+
|
85
|
+
embedded.each do |key, value|
|
86
|
+
@embedded_resources[key.to_sym] =
|
87
|
+
if value.is_a? Array
|
88
|
+
value.map { |d| BaseResource.new(d) }
|
89
|
+
else
|
90
|
+
BaseResource.new(value)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def method_missing(method_name, *args, &block)
|
96
|
+
if attributes.key?(method_name)
|
97
|
+
attribute(method_name)
|
98
|
+
else
|
99
|
+
super
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def respond_to_missing?(method_name, include_private = false)
|
104
|
+
return true if attributes.key?(method_name)
|
105
|
+
super
|
106
|
+
end
|
107
|
+
|
108
|
+
def transform_values_to_s(hash)
|
109
|
+
hash.transform_values do |value|
|
110
|
+
if value.is_a? Array
|
111
|
+
value.map(&:to_s)
|
112
|
+
else
|
113
|
+
value.to_s
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'shaf_client/link'
|
4
|
+
|
5
|
+
class ShafClient
|
6
|
+
class Curie < Link
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def self.from(data)
|
10
|
+
if data.is_a? Array
|
11
|
+
data.map do |d|
|
12
|
+
new(name: data['name'], href: d['href'], templated: d['templated'])
|
13
|
+
end
|
14
|
+
else
|
15
|
+
new(name: data['name'], href: data['href'], templated: data['templated'])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(name:, href:, templated: nil)
|
20
|
+
@name = name
|
21
|
+
@href = href
|
22
|
+
@templated = !!templated
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'shaf_client/link'
|
3
|
+
|
4
|
+
class ShafClient
|
5
|
+
class Form < Resource
|
6
|
+
|
7
|
+
def values
|
8
|
+
return @values if defined? @values
|
9
|
+
|
10
|
+
@values = attribute(:fields).each_with_object({}) do |d, v|
|
11
|
+
v[d['name'].to_sym] = d['value']
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
values[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(key, value)
|
20
|
+
values[key] = value
|
21
|
+
end
|
22
|
+
|
23
|
+
def target
|
24
|
+
attribute(:href)
|
25
|
+
end
|
26
|
+
|
27
|
+
def http_method
|
28
|
+
attribute(:method).downcase.to_sym
|
29
|
+
end
|
30
|
+
|
31
|
+
# def validate; end
|
32
|
+
|
33
|
+
def submit
|
34
|
+
client.send(http_method, target, @values)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ShafClient
|
4
|
+
class Link
|
5
|
+
attr_reader :templated
|
6
|
+
|
7
|
+
def self.from(data)
|
8
|
+
if data.is_a? Array
|
9
|
+
data.map { |d| new(href: d['href'], templated: d['templated']) }
|
10
|
+
else
|
11
|
+
new(href: data['href'], templated: data['templated'])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(href:, templated: nil)
|
16
|
+
@href = href
|
17
|
+
@templated = !!templated
|
18
|
+
end
|
19
|
+
|
20
|
+
alias templated? templated
|
21
|
+
|
22
|
+
def href
|
23
|
+
@href.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve_templated(**args)
|
27
|
+
return unless templated?
|
28
|
+
|
29
|
+
args.inject(href) do |uri, (key, value)|
|
30
|
+
value = value.to_s.sub(/.+:/, '')
|
31
|
+
uri.sub(/{#{key}}/, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
{
|
37
|
+
href: href,
|
38
|
+
templated: templated?
|
39
|
+
}.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# FIXME zip payload
|
2
|
+
|
3
|
+
class ShafClient
|
4
|
+
module Middleware
|
5
|
+
class Cache
|
6
|
+
DEFAULT_THRESHOLD = 10_000
|
7
|
+
|
8
|
+
Response = Struct.new(:status, :body, :headers, keyword_init: true)
|
9
|
+
|
10
|
+
module Control
|
11
|
+
def cache_size
|
12
|
+
Cache.size
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear_cache
|
16
|
+
Cache.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear_stale_cache
|
20
|
+
Cache.clear_stale
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
attr_writer :threshold
|
26
|
+
|
27
|
+
def inc_request_count
|
28
|
+
@request_count ||= 0
|
29
|
+
@request_count += 1
|
30
|
+
return if (@request_count % 500 != 0)
|
31
|
+
clear_stale
|
32
|
+
check_threshold
|
33
|
+
end
|
34
|
+
|
35
|
+
def size
|
36
|
+
cache.size
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear
|
40
|
+
mutex.synchronize do
|
41
|
+
@cache = {}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def clear_stale
|
46
|
+
mutex.synchronize do
|
47
|
+
cache.delete_if { |_key, entry| expired? entry }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def get(key:, check_expiration: true)
|
52
|
+
entry = nil
|
53
|
+
mutex.synchronize do
|
54
|
+
entry = cache[key.to_sym].dup
|
55
|
+
end
|
56
|
+
return entry[:payload] if valid?(entry, check_expiration)
|
57
|
+
yield if block_given?
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_etag(key:)
|
61
|
+
mutex.synchronize do
|
62
|
+
cache.dig(key.to_sym, :etag)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def store(key:, payload:, etag: nil, expire_at: nil)
|
67
|
+
return unless payload && key && (etag || expire_at)
|
68
|
+
|
69
|
+
mutex.synchronize do
|
70
|
+
cache[key.to_sym] = {
|
71
|
+
payload: payload,
|
72
|
+
etag: etag,
|
73
|
+
expire_at: expire_at
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def threshold
|
79
|
+
@threshold ||= DEFAULT_THRESHOLD
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def mutex
|
85
|
+
@mutex = Mutex.new
|
86
|
+
end
|
87
|
+
|
88
|
+
def cache
|
89
|
+
mutex.synchronize do
|
90
|
+
@cache ||= {}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def valid?(entry, check_expiration = true)
|
95
|
+
return false unless entry
|
96
|
+
return false unless entry[:payload]
|
97
|
+
return true unless check_expiration
|
98
|
+
!expired? entry
|
99
|
+
end
|
100
|
+
|
101
|
+
def expired?(entry)
|
102
|
+
return true unless entry[:expire_at]
|
103
|
+
entry[:expire_at] < Time.now
|
104
|
+
end
|
105
|
+
|
106
|
+
def check_threshold
|
107
|
+
return if size < threshold
|
108
|
+
|
109
|
+
count = 500
|
110
|
+
cache.each do |key, _value|
|
111
|
+
break if count <= 0
|
112
|
+
cache[key] = nil
|
113
|
+
count -= 1
|
114
|
+
end
|
115
|
+
cache.compact!
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def initialize(app, **options)
|
120
|
+
@app = app
|
121
|
+
@options = options
|
122
|
+
end
|
123
|
+
|
124
|
+
def call(request_env)
|
125
|
+
key = cache_key(request_env)
|
126
|
+
|
127
|
+
if request_env[:method] == :get
|
128
|
+
cached = self.class.get(key: key)
|
129
|
+
return Response.new(body: cached, headers: {}) if cached
|
130
|
+
end
|
131
|
+
|
132
|
+
add_etag(request_env, key)
|
133
|
+
|
134
|
+
@app.call(request_env).on_complete do |response_env|
|
135
|
+
add_cached_payload(response_env, key)
|
136
|
+
cache_response(response_env, key)
|
137
|
+
self.class.inc_request_count
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_etag(env, key = nil)
|
142
|
+
key ||= cache_key(env)
|
143
|
+
etag = self.class.get_etag(key: key)
|
144
|
+
env[:request_headers]['If-None-Match'] = etag if etag
|
145
|
+
end
|
146
|
+
|
147
|
+
def add_cached_payload(response_env, key)
|
148
|
+
return if response_env[:status] != 304
|
149
|
+
cached = self.class.get(key: key, check_expiration: false)
|
150
|
+
response_env[:body] = cached if cached
|
151
|
+
end
|
152
|
+
|
153
|
+
def cache_response(response_env, key)
|
154
|
+
etag = response_env[:response_headers]['etag']
|
155
|
+
cache_control = response_env[:response_headers]['cache-control']
|
156
|
+
expire_at = expiration(cache_control)
|
157
|
+
self.class.store(
|
158
|
+
key: key,
|
159
|
+
payload: response_env[:body],
|
160
|
+
etag: etag,
|
161
|
+
expire_at: expire_at
|
162
|
+
)
|
163
|
+
end
|
164
|
+
|
165
|
+
def cache_key(env)
|
166
|
+
:"#{env[:url]}.#{env[:request_headers][auth_header]}"
|
167
|
+
end
|
168
|
+
|
169
|
+
def auth_header
|
170
|
+
@options.fetch(:auth_header, 'X-AUTH-TOKEN')
|
171
|
+
end
|
172
|
+
|
173
|
+
def expiration(cache_control)
|
174
|
+
return unless cache_control
|
175
|
+
|
176
|
+
max_age = cache_control[/max-age=\s?(\d+)/, 1]
|
177
|
+
Time.now + max_age.to_i if max_age
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'shaf_client/base_resource'
|
3
|
+
|
4
|
+
class ShafClient
|
5
|
+
class Resource < BaseResource
|
6
|
+
|
7
|
+
def initialize(client, payload)
|
8
|
+
@client = client
|
9
|
+
super(payload)
|
10
|
+
end
|
11
|
+
|
12
|
+
%i[get put post delete patch get_form].each do |method|
|
13
|
+
define_method(method) do |rel, payload = nil|
|
14
|
+
href = link(rel).href
|
15
|
+
args = [method, href]
|
16
|
+
args << payload unless method.to_s.start_with? 'get'
|
17
|
+
client.send(*args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_doc(rel:)
|
22
|
+
rel = rel.to_s
|
23
|
+
curie_name, rel =
|
24
|
+
if rel.include? ':'
|
25
|
+
rel.split(':')
|
26
|
+
else
|
27
|
+
[:doc, rel]
|
28
|
+
end
|
29
|
+
|
30
|
+
curie = curie(curie_name)
|
31
|
+
uri = curie.resolve_templated(rel: rel)
|
32
|
+
client.get_doc(uri)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :client
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shaf_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sammy Henningsson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDXjCCAkagAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFzYW1t
|
14
|
+
eS5oZW5uaW5nc3Nvbi9EQz1nbWFpbC9EQz1jb20wHhcNMTgwNzE2MTYzNTMzWhcN
|
15
|
+
MjAwNzE2MTYzNTMzWjAsMSowKAYDVQQDDCFzYW1teS5oZW5uaW5nc3Nvbi9EQz1n
|
16
|
+
bWFpbC9EQz1jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvkgwt
|
17
|
+
Zn8obnCelWttayB1BrHBLUK3b8gasRRtbNk4DzAL+EW6sHSVT2u5I7Wws7JQA5VB
|
18
|
+
NaK7tgvq3CbDLVRl9NrpDCDx09To08stPxDKi6kst1nkSPAD8g0sQlW3voeQTH98
|
19
|
+
2Z2H3XUegHhu5Z9PU9T/7V/vZUzHPiPg1tX1JUIGOPAjVGsr7SUetbL171zK4S4Y
|
20
|
+
tvUkIoNaph+maHttvyYB/ptiZLD53WORKd4Knw3OiJsLtrxr5hhKyQ+txQdF0P8G
|
21
|
+
+FlR+Je7B0Ek3yg6fEiJgrdcajYCMo8Oe/GRtoHhi6J3LsYA620P1BSCddZQ2XeL
|
22
|
+
y3rzIZyMU0iaT69nAgMBAAGjgYowgYcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
|
23
|
+
HQYDVR0OBBYEFLpI49QndnmuiDhwy2XtMps7No1pMCYGA1UdEQQfMB2BG3NhbW15
|
24
|
+
Lmhlbm5pbmdzc29uQGdtYWlsLmNvbTAmBgNVHRIEHzAdgRtzYW1teS5oZW5uaW5n
|
25
|
+
c3NvbkBnbWFpbC5jb20wDQYJKoZIhvcNAQELBQADggEBAFJZqH6sgeiTLvMLpxaK
|
26
|
+
K1GaYSCyZbMutf5C3tIAgkmU5UD6B8R0bw6gTM1deM5NJ60LjzqY7rlK3YKDIbTn
|
27
|
+
iXMCe9vd4yE/jb5Zi8Wk//9n8CMG68dQpBvmcQ58/M4gTtgsx+lIgXuI5dPQMmRi
|
28
|
+
bhWQqqWqxT9X6njjfXFk4xn3z6mfFQNPAYqRVeTHUpXBQZPt+bYXRwHPFZGWkx4l
|
29
|
+
BnuuhYKt3CR7YIgvnsQWlTAcU1Ipdayj6UfYqUtlc6cF3CL96NOx7mgZXV8URFiX
|
30
|
+
ZMhjYR7sRczGJx+GxGU2EaR0bjRsPVlC4ywtFxoOfRG3WaJcpWGEoAoMJX6Z0bRv
|
31
|
+
M40=
|
32
|
+
-----END CERTIFICATE-----
|
33
|
+
date: 2018-12-09 00:00:00.000000000 Z
|
34
|
+
dependencies:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: faraday
|
37
|
+
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.15'
|
42
|
+
type: :runtime
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0.15'
|
49
|
+
description: A HAL client customized for Shaf APIs
|
50
|
+
email: sammy.henningsson@gmail.com
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- lib/shaf_client.rb
|
56
|
+
- lib/shaf_client/base_resource.rb
|
57
|
+
- lib/shaf_client/curie.rb
|
58
|
+
- lib/shaf_client/form.rb
|
59
|
+
- lib/shaf_client/link.rb
|
60
|
+
- lib/shaf_client/middleware/cache.rb
|
61
|
+
- lib/shaf_client/resource.rb
|
62
|
+
homepage: https://github.com/sammyhenningsson/shafClient
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.5'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.7.6
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: HAL client for Shaf
|
86
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|