shaf_client 0.7.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4eda6aea2ca9040216f1dee7732b7123e98edfbbec2d3b53dd567f50940d145
4
- data.tar.gz: a1d43989ce6bff97ac6801ef4fcb67f77e01933cbdf796694e6339d57606d9d0
3
+ metadata.gz: 11ccc3070c77ca9f04b3a54599437752022c2de7b6bf51f5d3cf7d6bf25bb147
4
+ data.tar.gz: 73658cc5c27287a677e82a935ced861e8775355ee84df02bc10631e33a13a2e8
5
5
  SHA512:
6
- metadata.gz: d0ca1c6347bf9fb9d15eab004cf7cc83c5f9d571f32cb0fa65c8aaec179c03f9a6f6cd1762951d9904c2eecd537ea0d2b0d04ff347c171099541c7ef1628f9f3
7
- data.tar.gz: 976c5ce8cd4e7868c957c7b4c74696298cb7b262ddb314a359efd28e52b6aa4c1925fe698718eed75472acf646737b12cddedaefb7bb9311026e9599fc934ef3
6
+ metadata.gz: 322b0537cb301169f77dc76b078c11d74d60b156718b9bdef1cf019d3983fb2c6e3aab01750bd309b6e7e672e0fa7f987b74d2ddd6d0edac21ff03088ddb724e
7
+ data.tar.gz: 3d8f6b58ed02af7892425fa39eb1bfb9f52845cba81cff2a8e9204e2dd1780ceafb8bf6b13f2b12f77a7ee6a74ecafcca60a631dacf28dd66e06c7d98a3b4726
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/bin/shaf_client ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(__dir__, '../lib/')
4
+
5
+ require 'irb'
6
+ require 'optparse'
7
+ require 'shaf_client'
8
+
9
+ url = ARGV.shift || String(ENV['SHAF_CLIENT_URL'])
10
+ options = {
11
+ user: ENV['SHAF_CLIENT_USER'],
12
+ password: ENV['SHAF_CLIENT_PASSWORD']
13
+ }
14
+
15
+ OptionParser.new do |opts|
16
+ opts.banner = "Usage: shaf_client [url]"
17
+
18
+ opts.on("-u", "--user user", "Username used for authentication") do |user|
19
+ options[:user] = user
20
+ end
21
+
22
+ opts.on("-p", "--password password", "Password used for authentication") do |pass|
23
+ options[:password] = pass
24
+ end
25
+ end.parse! ARGV
26
+
27
+ client = ShafClient.new(url, **options) unless url.empty?
28
+ TOPLEVEL_BINDING.local_variable_set(:client, client)
29
+
30
+ IRB.start
data/lib/shaf_client.rb CHANGED
@@ -16,6 +16,7 @@ require 'shaf_client/shaf_form'
16
16
  require 'shaf_client/hal_form'
17
17
  require 'shaf_client/api_error'
18
18
  require 'shaf_client/problem_json'
19
+ require 'shaf_client/alps_json'
19
20
  require 'shaf_client/empty_resource'
20
21
  require 'shaf_client/unknown_resource'
21
22
  require 'shaf_client/hypertext_cache_strategy'
@@ -25,6 +26,12 @@ class ShafClient
25
26
  include MimeTypes
26
27
 
27
28
  DEFAULT_ADAPTER = :net_http
29
+ DEFAULT_ACCEPT_HEADER = [
30
+ MIME_TYPE_HAL,
31
+ MIME_TYPE_PROBLEM_JSON,
32
+ MIME_TYPE_ALPS_JSON,
33
+ '*/*;q=0.8',
34
+ ].join(', ')
28
35
 
29
36
  def initialize(root_uri, **options)
30
37
  @root_uri = root_uri.dup
@@ -55,11 +62,6 @@ class ShafClient
55
62
  end
56
63
  end
57
64
 
58
- def stubs
59
- return unless @adapter == :test
60
- @stubs ||= Faraday::Adapter::Test::Stubs.new
61
- end
62
-
63
65
  private
64
66
 
65
67
  attr_reader :options, :auth_header
@@ -67,7 +69,7 @@ class ShafClient
67
69
  def setup_default_headers
68
70
  @default_headers = {
69
71
  'Content-Type' => options.fetch(:content_type, MIME_TYPE_JSON),
70
- 'Accept' => options.fetch(:accept, MIME_TYPE_HAL)
72
+ 'Accept' => options.fetch(:accept, DEFAULT_ACCEPT_HEADER)
71
73
  }
72
74
  return unless token = options[:auth_token]
73
75
 
@@ -105,9 +107,11 @@ class ShafClient
105
107
  end
106
108
 
107
109
  def connect_adapter(connection)
108
- args = [@adapter]
109
- args << stubs if @adapter == :test
110
- connection.adapter(*args)
110
+ connection.adapter(*adapter_args)
111
+ end
112
+
113
+ def adapter_args
114
+ [@adapter]
111
115
  end
112
116
 
113
117
  def request(method:, uri:, payload: nil, opts: {})
@@ -0,0 +1,60 @@
1
+ require 'shaf_client/alps/extension'
2
+
3
+ class ShafClient
4
+ module Alps
5
+ class Descriptor
6
+ attr_reader :id, :href, :name, :type, :doc, :ext
7
+
8
+ def initialize(id:, **kwargs)
9
+ @id = id.to_sym
10
+ @href = kwargs[:href]
11
+ @name = kwargs[:name]
12
+ @type = kwargs[:type]
13
+ @doc = kwargs[:doc]
14
+ @ext = parse_extentions(kwargs[:ext])
15
+ end
16
+
17
+ alias extensions ext
18
+
19
+ def to_h
20
+ {
21
+ id: id,
22
+ href: href,
23
+ name: name,
24
+ type: type,
25
+ doc: doc,
26
+ ext: extensions.map(&:to_h),
27
+ }
28
+ end
29
+
30
+ def semantic?
31
+ type == 'semantic'
32
+ end
33
+
34
+ def safe?
35
+ type == 'safe'
36
+ end
37
+
38
+ def idempotent?
39
+ type == 'idempotent'
40
+ end
41
+
42
+ def unsafe?
43
+ type == 'unsafe'
44
+ end
45
+
46
+ def extension(id)
47
+ extensions.find { |ext| ext.id == id.to_sym }
48
+ end
49
+
50
+ private
51
+
52
+ def parse_extentions(extensions)
53
+ extensions ||= []
54
+ extensions = [extensions] unless extensions.is_a? Array
55
+ extensions.map { |ext| Extension.new(**ext.transform_keys(&:to_sym)) }
56
+ end
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,35 @@
1
+ class ShafClient
2
+ module Alps
3
+ class Extension
4
+ attr_reader :id, :href, :value
5
+
6
+ def initialize(id:, href: nil, value: nil)
7
+ @id = id.to_sym
8
+ @href = href
9
+ @value = value
10
+ end
11
+
12
+ def to_h
13
+ {
14
+ id: id,
15
+ href: href,
16
+ value: value,
17
+ }
18
+ end
19
+
20
+ private
21
+
22
+ def method_missing(method_name, *args, &block)
23
+ name = method_name.to_s
24
+ return super unless name.end_with? '?'
25
+
26
+ id.to_s == name[0..-2]
27
+ end
28
+
29
+ def respond_to_missing?(method_name, include_private = false)
30
+ return true if method_name.to_s.end_with? '?'
31
+ super
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ require 'shaf_client/alps/descriptor'
2
+
3
+ class ShafClient
4
+ class AlpsJson < Resource
5
+ content_type MIME_TYPE_ALPS_JSON
6
+
7
+ attr_reader :descriptors
8
+
9
+ def initialize(_client, payload, status = nil, headers = {})
10
+ super
11
+
12
+ @links = {}.freeze
13
+ @curies = {}.freeze
14
+ @embedded_resources = {}.freeze
15
+ end
16
+
17
+ def to_h
18
+ attributes.merge(
19
+ descriptors: descriptors.map(&:to_h)
20
+ )
21
+ end
22
+
23
+ def descriptor(id)
24
+ descriptors.find { |desc| desc.id == id.to_sym }
25
+ end
26
+
27
+ def each_descriptor(&block)
28
+ descriptors.each(&block)
29
+ end
30
+
31
+ private
32
+
33
+ def parse
34
+ alps = payload&.dig('alps') || {}
35
+ @attributes = {
36
+ version: alps['version'],
37
+ doc: alps['doc'],
38
+ }
39
+ @descriptors = alps.fetch('descriptor', []).map do |desc|
40
+ Alps::Descriptor.new(**desc.transform_keys(&:to_sym))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -154,13 +154,17 @@ class ShafClient
154
154
  embedded.each do |key, value|
155
155
  @embedded_resources[key.to_sym] =
156
156
  if value.is_a? Array
157
- value.map { |d| BaseResource.new(d) }
157
+ value.map { |d| build_embedded_resource(d) }
158
158
  else
159
- BaseResource.new(value)
159
+ build_embedded_resource(value)
160
160
  end
161
161
  end
162
162
  end
163
163
 
164
+ def build_embedded_resource(payload)
165
+ BaseResource.new(payload)
166
+ end
167
+
164
168
  def method_missing(method_name, *args, &block)
165
169
  return super unless attributes.key?(method_name)
166
170
  attribute(method_name)
@@ -0,0 +1,53 @@
1
+ require 'forwardable'
2
+
3
+ class ShafClient
4
+ class ContentTypeMap
5
+ extend Forwardable
6
+
7
+ def_delegators :@map, :default, :default=, :keys, :values, :each
8
+
9
+ def initialize
10
+ @map = {}
11
+ end
12
+
13
+ def [](content_type, profile = nil)
14
+ key = key_for(content_type, profile)
15
+ map.fetch(key) do
16
+ key = key_for(content_type, nil)
17
+ map[key]
18
+ end
19
+ end
20
+
21
+ def []=(content_type, profile = nil, value)
22
+ key = key_for(content_type, profile)
23
+ map[key] = value
24
+ end
25
+
26
+ def key?(content_type, profile = nil)
27
+ key = key_for(content_type, profile)
28
+ map.key? key
29
+ end
30
+
31
+ def delete(content_type, profile = nil)
32
+ key = key_for(content_type, profile)
33
+ map.delete(key)
34
+ end
35
+
36
+ def key_for(content_type, profile)
37
+ return unless content_type
38
+
39
+ key = content_type.to_s.downcase
40
+ key = strip_parameters(key)
41
+ key << "_#{profile.to_s.downcase}" if profile
42
+ key
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :map
48
+
49
+ def strip_parameters(content_type)
50
+ content_type&.sub(/;.*/, '')
51
+ end
52
+ end
53
+ end
@@ -24,7 +24,7 @@ class ShafClient
24
24
 
25
25
  def fields
26
26
  template[:properties].map do |values|
27
- Field.new(values.transform_keys(&:to_sym))
27
+ Field.new(**values.transform_keys(&:to_sym))
28
28
  end
29
29
  end
30
30
 
@@ -18,10 +18,6 @@ class ShafClient
18
18
  def default_http_status
19
19
  203
20
20
  end
21
-
22
- def default_headers
23
- {'content-type' => 'application/hal+json'}
24
- end
25
21
  end
26
22
 
27
23
  def default_hypertext_cache_strategy
@@ -27,8 +27,8 @@ class ShafClient
27
27
  return href unless templated?
28
28
 
29
29
  href
30
- .then { |href| resolve_required(href, **args) }
31
- .then { |href| resolve_optional(href, **args) }
30
+ .yield_self { |href| resolve_required(href, **args) }
31
+ .yield_self { |href| resolve_optional(href, **args) }
32
32
  end
33
33
 
34
34
  def to_h
@@ -2,5 +2,7 @@ class ShafClient
2
2
  module MimeTypes
3
3
  MIME_TYPE_JSON = 'application/json'
4
4
  MIME_TYPE_HAL = 'application/hal+json'
5
+ MIME_TYPE_PROBLEM_JSON = 'application/problem+json'
6
+ MIME_TYPE_ALPS_JSON = 'application/alps+json'
5
7
  end
6
8
  end
@@ -5,7 +5,7 @@ class ShafClient
5
5
  class ProblemJson < Resource
6
6
  include StatusCodes
7
7
 
8
- content_type 'application/problem+json'
8
+ content_type MIME_TYPE_PROBLEM_JSON
9
9
 
10
10
  def type
11
11
  attribute(:type) { 'about:blank' }
@@ -10,17 +10,28 @@ class ShafClient
10
10
 
11
11
  ResourceMapper.register(MIME_TYPE_HAL, self)
12
12
 
13
- def self.content_type(type)
14
- ResourceMapper.register(type, self)
13
+ def self.content_type(type, profile: nil)
14
+ ResourceMapper.register(type, profile, self)
15
15
  end
16
16
 
17
17
  def self.profile(name)
18
- content_type "#{MIME_TYPE_HAL};profile=#{name}"
18
+ content_type MIME_TYPE_HAL, profile: name
19
19
  end
20
20
 
21
21
  def self.build(client, payload, content_type = MIME_TYPE_HAL, status = nil, headers = {})
22
- ResourceMapper.for(content_type)
23
- .new(client, payload, status, headers)
22
+ resource_class, extensions = ResourceMapper.for(
23
+ content_type: content_type,
24
+ headers: headers,
25
+ payload: payload,
26
+ client: client,
27
+ )
28
+ resrc = resource_class.new(client, payload, status, headers)
29
+ extensions.compact.each { |extension| resrc.extend extension }
30
+ resrc
31
+ end
32
+
33
+ def self.default_resource_class!
34
+ ResourceMapper.default = self
24
35
  end
25
36
 
26
37
  def initialize(client, payload, status = nil, headers = {})
@@ -63,7 +74,7 @@ class ShafClient
63
74
 
64
75
  curie = curie(curie_name)
65
76
  uri = curie.resolve_templated(rel: rel)
66
- client.get(uri, options)
77
+ client.get(uri, **options)
67
78
  end
68
79
 
69
80
  def get_hal_form(rel)
@@ -96,6 +107,7 @@ class ShafClient
96
107
  protected
97
108
 
98
109
  def <<(other)
110
+ @client = other.client
99
111
  @http_status = other.http_status.dup
100
112
  @headers = other.headers.dup
101
113
  super
@@ -105,6 +117,16 @@ class ShafClient
105
117
 
106
118
  attr_reader :client
107
119
 
120
+ def build_embedded_resource(payload)
121
+ self.class.build(
122
+ client,
123
+ payload,
124
+ headers['content-type'],
125
+ http_status,
126
+ headers
127
+ )
128
+ end
129
+
108
130
  def hypertext_cache_strategy(options)
109
131
  options.fetch(:hypertext_cache_strategy) do
110
132
  ShafClient.default_hypertext_cache_strategy
@@ -122,13 +144,13 @@ class ShafClient
122
144
  return unless HypertextCacheStrategy.cacheable? cache_strategy
123
145
 
124
146
  if HypertextCacheStrategy.fetch_headers? cache_strategy
125
- resource = client.head(href, options)
147
+ resource = client.head(href, **options)
126
148
  status = resource.http_status
127
149
  headers = resource.headers
128
150
  embedded_resource = embedded_resource.payload
129
151
  else
130
152
  status = HypertextCacheStrategy.default_http_status
131
- headers = HypertextCacheStrategy.default_headers
153
+ headers = embedded_resource.headers
132
154
  end
133
155
 
134
156
  self.class.build(client, embedded_resource, headers['content-type'], status, headers)
@@ -0,0 +1,36 @@
1
+ require 'set'
2
+
3
+ class ShafClient
4
+ module ResourceExtension
5
+ class << self
6
+ def register(extender)
7
+ extenders << extender
8
+ end
9
+
10
+ def unregister(extender)
11
+ extenders.delete(extender)
12
+ end
13
+
14
+ def for(profile, base, link_relations, client)
15
+ link_relations = remove_curies(link_relations)
16
+ extenders.map { |extender| extender.call(profile, base, link_relations, client) }
17
+ .compact
18
+ end
19
+
20
+ private
21
+
22
+ def extenders
23
+ @extenders ||= Set.new
24
+ end
25
+
26
+ def remove_curies(link_relations)
27
+ Array(link_relations).map do |rel|
28
+ rel.to_s.sub(/[^:]*:/, '').to_sym
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ require 'shaf_client/resource_extension/base'
36
+ require 'shaf_client/resource_extension/alps_http_method'
@@ -0,0 +1,67 @@
1
+ class ShafClient
2
+ module ResourceExtension
3
+ class AlpsHttpMethod < Base
4
+ class << self
5
+ def call(profile, base, link_relations, _client)
6
+ return unless profile.is_a? AlpsJson
7
+ return unless base <= Resource
8
+
9
+ link_relations = Array(link_relations).compact
10
+ descriptors = descriptors_with_http_method(profile)
11
+ descriptors.keep_if do |descriptor|
12
+ link_relations.include? identifier_for(descriptor)&.to_sym
13
+ end
14
+
15
+ extension_for(descriptors)
16
+ end
17
+
18
+ private
19
+
20
+ def descriptors_with_http_method(profile)
21
+ profile.each_descriptor.each_with_object([]) do |descriptor, descriptors|
22
+ next unless descriptor.extension(:http_method)
23
+ descriptors << descriptor
24
+ end
25
+ end
26
+
27
+ def extension_for(descriptors)
28
+ return if descriptors.empty?
29
+
30
+ Module.new.tap do |mod|
31
+ descriptors.each do |descriptor|
32
+ add_method(mod, descriptor, methods.first)
33
+ end
34
+ end
35
+ end
36
+
37
+ def add_method(mod, descriptor, method)
38
+ rel = identifier_for(descriptor)
39
+ return unless rel
40
+
41
+ ext = descriptor.extension(:http_method)
42
+ methods = Array(ext&.value)
43
+
44
+ # We only know what method to use when size is 1
45
+ return unless methods.size == 1
46
+
47
+ http_method = methods.first.downcase.to_sym
48
+ name = method_name_from(rel)
49
+
50
+ mod.define_method(name) do |payload: nil, **options|
51
+ href = link(rel).href
52
+ client.send(http_method, href, payload: payload, **options)
53
+ end
54
+ end
55
+
56
+ def method_name_from(rel)
57
+ "#{rel.to_s.downcase.tr('-', '_')}!"
58
+ end
59
+
60
+ def identifier_for(descriptor)
61
+ # Currently we only support `id` (i.e no support for descriptors with `href`)
62
+ descriptor.id
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ class ShafClient
2
+ module ResourceExtension
3
+ class Base
4
+ def self.inherited(mod)
5
+ ResourceExtension.register(mod)
6
+ end
7
+
8
+ def self.call(*args)
9
+ raise NotImplementedError, "Class '#{self}' must respond to `call`"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,22 +1,26 @@
1
1
  require 'shaf_client/error'
2
+ require 'shaf_client/content_type_map'
3
+ require 'shaf_client/resource_extension'
2
4
 
3
5
  class ShafClient
4
- class ResourceMapper
6
+ module ResourceMapper
5
7
  class << self
6
- def for(content_type)
7
- mapping[content_type&.to_sym].tap do |clazz|
8
- next if clazz
9
- raise UnSupportedContentType,
10
- "Can't handle Content-Type: #{content_type}"
11
- end
8
+ def for(content_type:, headers: {}, payload: nil, client: nil)
9
+ content_type = content_type&.to_sym
10
+ profile = profile_from(content_type, headers, payload)
11
+ clazz, extensions = result_for(content_type, payload, profile, client)
12
+
13
+ raise_unsupported_error(content_type) unless clazz
14
+
15
+ [clazz, extensions]
12
16
  end
13
17
 
14
- def register(content_type, clazz)
15
- mapping[content_type&.to_sym] = clazz
18
+ def register(content_type, profile = nil, clazz)
19
+ mapping[content_type&.to_sym, profile] = clazz
16
20
  end
17
21
 
18
- def unregister(content_type)
19
- mapping.delete(content_type.to_sym)
22
+ def unregister(content_type, profile = nil)
23
+ mapping.delete(content_type.to_sym, profile)
20
24
  end
21
25
 
22
26
  def default=(clazz)
@@ -26,7 +30,75 @@ class ShafClient
26
30
  private
27
31
 
28
32
  def mapping
29
- @mapping ||= {}
33
+ @mapping ||= ContentTypeMap.new
34
+ end
35
+
36
+ def result_for(content_type, payload, profile, client)
37
+ clazz = nil
38
+ extensions = []
39
+
40
+ # Note: mapping typically has a default value, so we need to check that the key really exist
41
+ if mapping.key? content_type, profile
42
+ # Registered classes with profile takes precedence over linked profiles
43
+ clazz = mapping[content_type, profile]
44
+ else
45
+ clazz = mapping[content_type]
46
+ extensions = extensions_for(clazz, profile, payload, client) if profile
47
+ end
48
+
49
+ [clazz, extensions]
50
+ end
51
+
52
+ def profile_from(content_type, headers, payload)
53
+ profile_from_content_type(content_type) ||
54
+ profile_from_link_header(headers) ||
55
+ profile_from_payload_link(content_type, payload)
56
+ rescue StandardError => err
57
+ warn "Exception while looking up profile link relation: #{err}"
58
+ end
59
+
60
+ def profile_from_content_type(content_type)
61
+ return unless content_type
62
+
63
+ content_type[/profile="?([^"\s;]*)/, 1]
64
+ end
65
+
66
+ def profile_from_link_header(headers)
67
+ links = String(headers["link"] || headers["Link"]).split(',')
68
+ profile_link = links.find { |link| link.match?(/rel="?profile"?/) }
69
+ profile_link[/<(.*)>/, 1] if profile_link
70
+ end
71
+
72
+ def profile_from_payload_link(content_type, payload)
73
+ clazz = mapping[content_type]
74
+ resource = clazz&.new(nil, payload)
75
+ return unless resource.respond_to? :link
76
+
77
+ link = resource.link(:profile) { nil }
78
+ link&.href
79
+ end
80
+
81
+ def extensions_for(clazz, profile, payload, client)
82
+ return [] unless clazz && profile && client
83
+
84
+ profile_resource = fetch_profile(profile, client)
85
+ link_relations = clazz.new(nil, payload).actions if payload
86
+
87
+ ResourceExtension.for(profile_resource, clazz, link_relations, client)
88
+ rescue StandardError => err
89
+ warn "Exception while resolving extensions for profile " \
90
+ "#{profile_resource&.name || profile}: #{err}"
91
+ []
92
+ end
93
+
94
+ def fetch_profile(profile, client)
95
+ return unless profile&.start_with? %r{https?://}
96
+
97
+ client.get(profile)
98
+ end
99
+
100
+ def raise_unsupported_error(content_type)
101
+ raise UnSupportedContentType, "Can't handle Content-Type: #{content_type}"
30
102
  end
31
103
  end
32
104
  end
@@ -27,7 +27,7 @@ class ShafClient
27
27
 
28
28
  def fields
29
29
  attribute(:fields).map do |values|
30
- Field.new(values.transform_keys(&:to_sym))
30
+ Field.new(**values.transform_keys(&:to_sym))
31
31
  end
32
32
  end
33
33
  end
@@ -0,0 +1,16 @@
1
+ class ShafClient
2
+ module Test
3
+ module Stubbing
4
+ def stubs
5
+ return unless @adapter == :test
6
+ @stubs ||= Faraday::Adapter::Test::Stubs.new
7
+ end
8
+
9
+ def adapter_args
10
+ args = super
11
+ args << stubs if @adapter == :test
12
+ args
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,9 +2,9 @@ require 'shaf_client/resource'
2
2
 
3
3
  class ShafClient
4
4
  class UnknownResource < Resource
5
- attr_reader :http_status, :headers, :body
5
+ default_resource_class!
6
6
 
7
- ResourceMapper.default = self
7
+ attr_reader :http_status, :headers, :body
8
8
 
9
9
  def initialize(_client, payload, status = nil, headers = {})
10
10
  @body = payload.freeze
@@ -1,3 +1,3 @@
1
1
  class ShafClient
2
- VERSION = "0.7.1"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaf_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -10,27 +10,26 @@ bindir: bin
10
10
  cert_chain:
11
11
  - |
12
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=
13
+ MIIDVjCCAj6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAqMSgwJgYDVQQDDB9zYW1t
14
+ eS5oZW5uaW5nc3Nvbi9EQz1oZXkvREM9Y29tMB4XDTIxMDIwMjEzNTY1OFoXDTIy
15
+ MDIwMjEzNTY1OFowKjEoMCYGA1UEAwwfc2FtbXkuaGVubmluZ3Nzb24vREM9aGV5
16
+ L0RDPWNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+SDC1mfyhu
17
+ cJ6Va21rIHUGscEtQrdvyBqxFG1s2TgPMAv4RbqwdJVPa7kjtbCzslADlUE1oru2
18
+ C+rcJsMtVGX02ukMIPHT1OjTyy0/EMqLqSy3WeRI8APyDSxCVbe+h5BMf3zZnYfd
19
+ dR6AeG7ln09T1P/tX+9lTMc+I+DW1fUlQgY48CNUayvtJR61svXvXMrhLhi29SQi
20
+ g1qmH6Zoe22/JgH+m2JksPndY5Ep3gqfDc6Imwu2vGvmGErJD63FB0XQ/wb4WVH4
21
+ l7sHQSTfKDp8SImCt1xqNgIyjw578ZG2geGLoncuxgDrbQ/UFIJ11lDZd4vLevMh
22
+ nIxTSJpPr2cCAwEAAaOBhjCBgzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNV
23
+ HQ4EFgQUukjj1Cd2ea6IOHDLZe0ymzs2jWkwJAYDVR0RBB0wG4EZc2FtbXkuaGVu
24
+ bmluZ3Nzb25AaGV5LmNvbTAkBgNVHRIEHTAbgRlzYW1teS5oZW5uaW5nc3NvbkBo
25
+ ZXkuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBt310FZ56E/fp/y5Wym1xb4C0owfnI
26
+ LzUqOjXWZTO7RezlBJV/qIwqt6bEjYDQR56zULJFSp4YdoDsratmQ+/kwtbHF7xf
27
+ WYkSE36mhLP2ggQFH9fXtX6XdyIlwFqwEfNW73ZrkBXGjMxLVKIS9uHdN7PoNhbS
28
+ 0YjOZZD/rq1Jf+klwl/G7bBDPjn58DWlUmwzoj49goGS/UBG37RssQxRwPelKHZh
29
+ 5ZlcHq9h5CxVt380OKaU6wMg95RJBd/kUJqmPxxlxMH8QDQinTwZmmFA9wW7PJdy
30
+ wAx8px9LkSjTs0GVLH7VtVRWAELllsswCJktz63Adelx9fmIMgrTYgZM
32
31
  -----END CERTIFICATE-----
33
- date: 2020-05-16 00:00:00.000000000 Z
32
+ date: 2021-03-12 00:00:00.000000000 Z
34
33
  dependencies:
35
34
  - !ruby/object:Gem::Dependency
36
35
  name: faraday
@@ -83,7 +82,7 @@ dependencies:
83
82
  version: '5'
84
83
  - - ">="
85
84
  - !ruby/object:Gem::Version
86
- version: '5.14'
85
+ version: 5.14.3
87
86
  type: :development
88
87
  prerelease: false
89
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -93,17 +92,37 @@ dependencies:
93
92
  version: '5'
94
93
  - - ">="
95
94
  - !ruby/object:Gem::Version
96
- version: '5.14'
95
+ version: 5.14.3
96
+ - !ruby/object:Gem::Dependency
97
+ name: minitest-hooks
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1'
97
110
  description: A HAL client customized for Shaf APIs
98
111
  email: sammy.henningsson@gmail.com
99
- executables: []
112
+ executables:
113
+ - shaf_client
100
114
  extensions: []
101
115
  extra_rdoc_files: []
102
116
  files:
117
+ - bin/shaf_client
103
118
  - lib/faraday_http_cache_patch.rb
104
119
  - lib/shaf_client.rb
120
+ - lib/shaf_client/alps/descriptor.rb
121
+ - lib/shaf_client/alps/extension.rb
122
+ - lib/shaf_client/alps_json.rb
105
123
  - lib/shaf_client/api_error.rb
106
124
  - lib/shaf_client/base_resource.rb
125
+ - lib/shaf_client/content_type_map.rb
107
126
  - lib/shaf_client/curie.rb
108
127
  - lib/shaf_client/empty_resource.rb
109
128
  - lib/shaf_client/error.rb
@@ -116,9 +135,13 @@ files:
116
135
  - lib/shaf_client/mime_types.rb
117
136
  - lib/shaf_client/problem_json.rb
118
137
  - lib/shaf_client/resource.rb
138
+ - lib/shaf_client/resource_extension.rb
139
+ - lib/shaf_client/resource_extension/alps_http_method.rb
140
+ - lib/shaf_client/resource_extension/base.rb
119
141
  - lib/shaf_client/resource_mapper.rb
120
142
  - lib/shaf_client/shaf_form.rb
121
143
  - lib/shaf_client/status_codes.rb
144
+ - lib/shaf_client/test/stubbing.rb
122
145
  - lib/shaf_client/unknown_resource.rb
123
146
  - lib/shaf_client/version.rb
124
147
  homepage: https://github.com/sammyhenningsson/shaf_client
metadata.gz.sig CHANGED
Binary file