shaf_client 0.6.2 → 1.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.
@@ -1,18 +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]
16
+ end
17
+
18
+ def register(content_type, profile = nil, clazz)
19
+ mapping[content_type&.to_sym, profile] = clazz
12
20
  end
13
21
 
14
- def register(content_type, clazz)
15
- mapping[content_type&.to_sym] = clazz
22
+ def unregister(content_type, profile = nil)
23
+ mapping.delete(content_type.to_sym, profile)
16
24
  end
17
25
 
18
26
  def default=(clazz)
@@ -22,7 +30,75 @@ class ShafClient
22
30
  private
23
31
 
24
32
  def mapping
25
- @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}"
26
102
  end
27
103
  end
28
104
  end
@@ -3,7 +3,8 @@ require 'shaf_client/form'
3
3
  class ShafClient
4
4
  class ShafForm < Form
5
5
 
6
- profile 'shaf-form'
6
+ profile 'shaf-form' # Legacy profiles
7
+ profile 'urn:shaf:form' # New style. Shaf version >= 2.1.0
7
8
 
8
9
  def title
9
10
  attribute(:title)
@@ -27,7 +28,7 @@ class ShafClient
27
28
 
28
29
  def fields
29
30
  attribute(:fields).map do |values|
30
- Field.new(values.transform_keys(&:to_sym))
31
+ Field.new(**values.transform_keys(&:to_sym))
31
32
  end
32
33
  end
33
34
  end
@@ -0,0 +1,70 @@
1
+ class ShafClient
2
+ module StatusCodes
3
+ StatusCode = {
4
+ 100 => 'Continue',
5
+ 101 => 'Switching Protocols',
6
+ 102 => 'Processing',
7
+ 103 => 'Early Hints',
8
+ 200 => 'OK',
9
+ 201 => 'Created',
10
+ 202 => 'Accepted',
11
+ 203 => 'Non-Authoritative Information',
12
+ 204 => 'No Content',
13
+ 205 => 'Reset Content',
14
+ 206 => 'Partial Content',
15
+ 207 => 'Multi-Status',
16
+ 208 => 'Already Reported',
17
+ 226 => 'IM Used',
18
+ 300 => 'Multiple Choices',
19
+ 301 => 'Moved Permanently',
20
+ 302 => 'Found',
21
+ 303 => 'See Other',
22
+ 304 => 'Not Modified',
23
+ 305 => 'Use Proxy',
24
+ 306 => '(Unused)',
25
+ 307 => 'Temporary Redirect',
26
+ 308 => 'Permanent Redirect',
27
+ 400 => 'Bad Request',
28
+ 401 => 'Unauthorized',
29
+ 402 => 'Payment Required',
30
+ 403 => 'Forbidden',
31
+ 404 => 'Not Found',
32
+ 405 => 'Method Not Allowed',
33
+ 406 => 'Not Acceptable',
34
+ 407 => 'Proxy Authentication Required',
35
+ 408 => 'Request Timeout',
36
+ 409 => 'Conflict',
37
+ 410 => 'Gone',
38
+ 411 => 'Length Required',
39
+ 412 => 'Precondition Failed',
40
+ 413 => 'Payload Too Large',
41
+ 414 => 'URI Too Long',
42
+ 415 => 'Unsupported Media Type',
43
+ 416 => 'Range Not Satisfiable',
44
+ 417 => 'Expectation Failed',
45
+ 421 => 'Misdirected Request',
46
+ 422 => 'Unprocessable Entity',
47
+ 423 => 'Locked',
48
+ 424 => 'Failed Dependency',
49
+ 425 => 'Too Early',
50
+ 426 => 'Upgrade Required',
51
+ 428 => 'Precondition Required',
52
+ 429 => 'Too Many Requests',
53
+ 431 => 'Request Header Fields Too Large',
54
+ 451 => 'Unavailable For Legal Reasons',
55
+ 500 => 'Internal Server Error',
56
+ 501 => 'Not Implemented',
57
+ 502 => 'Bad Gateway',
58
+ 503 => 'Service Unavailable',
59
+ 504 => 'Gateway Timeout',
60
+ 505 => 'HTTP Version Not Supported',
61
+ 506 => 'Variant Also Negotiates',
62
+ 507 => 'Insufficient Storage',
63
+ 508 => 'Loop Detected',
64
+ 510 => 'Not Extended',
65
+ 511 => 'Network Authentication Required',
66
+ }
67
+ StatusCode.default = 'Unassigned'
68
+ StatusCode.freeze
69
+ end
70
+ 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
@@ -22,7 +22,7 @@ class ShafClient
22
22
 
23
23
  %i[get put post delete patch, get_doc, reload!].each do |method|
24
24
  define_method(method) do |*_args|
25
- raise "UnknownResource: #{method} not available"
25
+ raise Error, "UnknownResource: #{method} not available"
26
26
  end
27
27
  end
28
28
  end
@@ -0,0 +1,3 @@
1
+ class ShafClient
2
+ VERSION = "1.1.0"
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.6.2
4
+ version: 1.1.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: 2019-10-04 00:00:00.000000000 Z
32
+ date: 2021-04-07 00:00:00.000000000 Z
34
33
  dependencies:
35
34
  - !ruby/object:Gem::Dependency
36
35
  name: faraday
@@ -38,14 +37,14 @@ dependencies:
38
37
  requirements:
39
38
  - - "~>"
40
39
  - !ruby/object:Gem::Version
41
- version: '0.15'
40
+ version: '1.0'
42
41
  type: :runtime
43
42
  prerelease: false
44
43
  version_requirements: !ruby/object:Gem::Requirement
45
44
  requirements:
46
45
  - - "~>"
47
46
  - !ruby/object:Gem::Version
48
- version: '0.15'
47
+ version: '1.0'
49
48
  - !ruby/object:Gem::Dependency
50
49
  name: faraday-http-cache
51
50
  requirement: !ruby/object:Gem::Requirement
@@ -66,14 +65,14 @@ dependencies:
66
65
  requirements:
67
66
  - - "~>"
68
67
  - !ruby/object:Gem::Version
69
- version: '12.0'
68
+ version: '13.0'
70
69
  type: :development
71
70
  prerelease: false
72
71
  version_requirements: !ruby/object:Gem::Requirement
73
72
  requirements:
74
73
  - - "~>"
75
74
  - !ruby/object:Gem::Version
76
- version: '12.0'
75
+ version: '13.0'
77
76
  - !ruby/object:Gem::Dependency
78
77
  name: minitest
79
78
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +82,7 @@ dependencies:
83
82
  version: '5'
84
83
  - - ">="
85
84
  - !ruby/object:Gem::Version
86
- version: '5.10'
85
+ version: 5.14.3
87
86
  type: :development
88
87
  prerelease: false
89
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -93,28 +92,58 @@ dependencies:
93
92
  version: '5'
94
93
  - - ">="
95
94
  - !ruby/object:Gem::Version
96
- version: '5.10'
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
118
+ - lib/faraday_http_cache_patch.rb
103
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
104
123
  - lib/shaf_client/api_error.rb
105
124
  - lib/shaf_client/base_resource.rb
125
+ - lib/shaf_client/content_type_map.rb
106
126
  - lib/shaf_client/curie.rb
107
127
  - lib/shaf_client/empty_resource.rb
108
128
  - lib/shaf_client/error.rb
109
129
  - lib/shaf_client/field.rb
110
130
  - lib/shaf_client/form.rb
111
131
  - lib/shaf_client/hal_form.rb
132
+ - lib/shaf_client/hypertext_cache_strategy.rb
112
133
  - lib/shaf_client/link.rb
113
134
  - lib/shaf_client/middleware/redirect.rb
135
+ - lib/shaf_client/mime_types.rb
136
+ - lib/shaf_client/problem_json.rb
114
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
115
141
  - lib/shaf_client/resource_mapper.rb
116
142
  - lib/shaf_client/shaf_form.rb
143
+ - lib/shaf_client/status_codes.rb
144
+ - lib/shaf_client/test/stubbing.rb
117
145
  - lib/shaf_client/unknown_resource.rb
146
+ - lib/shaf_client/version.rb
118
147
  homepage: https://github.com/sammyhenningsson/shaf_client
119
148
  licenses:
120
149
  - MIT
@@ -134,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
163
  - !ruby/object:Gem::Version
135
164
  version: '0'
136
165
  requirements: []
137
- rubygems_version: 3.0.6
166
+ rubygems_version: 3.0.3
138
167
  signing_key:
139
168
  specification_version: 4
140
169
  summary: HAL client for Shaf
metadata.gz.sig CHANGED
Binary file