shaf_client 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/shaf_client.rb +3 -2
- data/lib/shaf_client/curie.rb +5 -0
- data/lib/shaf_client/empty_resource.rb +1 -1
- data/lib/shaf_client/field.rb +75 -0
- data/lib/shaf_client/form.rb +45 -30
- data/lib/shaf_client/hal_form.rb +39 -0
- data/lib/shaf_client/link.rb +30 -7
- data/lib/shaf_client/resource.rb +15 -0
- data/lib/shaf_client/resource_mapper.rb +9 -7
- data/lib/shaf_client/shaf_form.rb +34 -0
- metadata +5 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19b9d623cc520b186b862d8604530daabf1723bc5a3b5d159dac3ecca706f1fb
|
4
|
+
data.tar.gz: 5ee331304969c4c873429914c521be63aaa849f94e5a09c94f6ba4fec06f9049
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85305d86a68ad781d0608aca92c595dca9403a7a420900560fc50828af4b6a663a3731fe7de10b73efaab75e2f0430a5f52ffce1003dcb32b511380e85577358
|
7
|
+
data.tar.gz: f9fc05a4f34e6dad3f83ee583fa8329ae665bf537522a7a1e950a818e97cc869a4109a73f909000cf4ef49a90e4571f595b54b679ce74cedd15826e775dc6a29
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/shaf_client.rb
CHANGED
@@ -6,7 +6,8 @@ require 'json'
|
|
6
6
|
require 'shaf_client/error'
|
7
7
|
require 'shaf_client/middleware/redirect'
|
8
8
|
require 'shaf_client/resource'
|
9
|
-
require 'shaf_client/
|
9
|
+
require 'shaf_client/shaf_form'
|
10
|
+
require 'shaf_client/hal_form'
|
10
11
|
require 'shaf_client/api_error'
|
11
12
|
require 'shaf_client/empty_resource'
|
12
13
|
require 'shaf_client/unknown_resource'
|
@@ -44,7 +45,7 @@ class ShafClient
|
|
44
45
|
)
|
45
46
|
|
46
47
|
body = String(response.body)
|
47
|
-
response.headers['content-type'] =
|
48
|
+
response.headers['content-type'] = nil if body.empty?
|
48
49
|
|
49
50
|
Resource.build(self, body, response.status, response.headers)
|
50
51
|
end
|
data/lib/shaf_client/curie.rb
CHANGED
@@ -4,7 +4,7 @@ class ShafClient
|
|
4
4
|
class EmptyResource < Resource
|
5
5
|
attr_reader :http_status, :headers
|
6
6
|
|
7
|
-
ResourceMapper.register(
|
7
|
+
ResourceMapper.register(nil, self)
|
8
8
|
|
9
9
|
def initialize(_client, _payload, status = nil, headers = {})
|
10
10
|
@http_status = status
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
class ShafClient
|
4
|
+
class Field
|
5
|
+
attr_reader :name, :prompt, :required, :read_only,
|
6
|
+
:hidden, :templated, :type, :value, :regex
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
name:,
|
10
|
+
prompt: nil,
|
11
|
+
title: nil,
|
12
|
+
required: false,
|
13
|
+
read_only: false,
|
14
|
+
hidden: false,
|
15
|
+
templated: false,
|
16
|
+
type: nil,
|
17
|
+
value: nil,
|
18
|
+
regex: nil
|
19
|
+
)
|
20
|
+
@name = name.to_sym
|
21
|
+
@prompt = prompt || title || name
|
22
|
+
@required = required
|
23
|
+
@read_only = read_only
|
24
|
+
@hidden = hidden
|
25
|
+
@templated = templated
|
26
|
+
@type = type&.downcase
|
27
|
+
@value = value
|
28
|
+
@regex = parse_regexp(regex)
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid?(value)
|
32
|
+
return false unless validate_required(value)
|
33
|
+
return false unless validate_number(value)
|
34
|
+
return false unless validate_string(value)
|
35
|
+
return false unless validate_regexp(value)
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def validate_required(value)
|
42
|
+
return true unless required
|
43
|
+
return false if String(value).empty?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_number(value)
|
48
|
+
return true if value.nil?
|
49
|
+
return true unless type
|
50
|
+
return true unless %w[int integer number].include? type
|
51
|
+
value.is_a? Numeric
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_string(value)
|
55
|
+
return true if value.nil?
|
56
|
+
return true unless type
|
57
|
+
return true unless %w[string text].include? type
|
58
|
+
value.is_a? String
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_regexp(value)
|
62
|
+
str = String(value)
|
63
|
+
return true if str.empty?
|
64
|
+
return true unless regex
|
65
|
+
str.match? regex
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_regexp(str)
|
69
|
+
return if String(str).empty?
|
70
|
+
Regexp.new(str)
|
71
|
+
rescue RegexpError
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/shaf_client/form.rb
CHANGED
@@ -1,42 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
4
|
+
require 'uri'
|
2
5
|
require 'shaf_client/link'
|
6
|
+
require 'shaf_client/field'
|
3
7
|
|
4
8
|
class ShafClient
|
5
9
|
class Form < Resource
|
6
10
|
|
7
|
-
profile 'shaf-form'
|
8
|
-
|
9
11
|
def values
|
10
12
|
return @values if defined? @values
|
11
13
|
|
12
|
-
@values =
|
13
|
-
|
14
|
+
@values = fields.each_with_object({}) do |field, values|
|
15
|
+
values[field.name] = field.value
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
17
19
|
def [](key)
|
18
|
-
values
|
20
|
+
values.fetch(key.to_sym)
|
19
21
|
end
|
20
22
|
|
21
23
|
def []=(key, value)
|
24
|
+
values.fetch(key.to_sym) # Raise KeyError unless key exist!
|
22
25
|
values[key.to_sym] = value
|
23
26
|
end
|
24
27
|
|
28
|
+
def title
|
29
|
+
raise NotImplementedError
|
30
|
+
end
|
31
|
+
|
25
32
|
def target
|
26
|
-
|
33
|
+
raise NotImplementedError
|
27
34
|
end
|
28
35
|
|
29
36
|
def http_method
|
30
|
-
|
37
|
+
raise NotImplementedError
|
38
|
+
end
|
39
|
+
|
40
|
+
def content_type
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
|
44
|
+
def fields
|
45
|
+
raise NotImplementedError
|
31
46
|
end
|
32
47
|
|
33
48
|
def submit
|
34
|
-
client.send(
|
49
|
+
client.send(
|
50
|
+
http_method,
|
51
|
+
target,
|
52
|
+
payload: encoded_payload,
|
53
|
+
headers: {'Content-Type' => content_type}
|
54
|
+
)
|
35
55
|
end
|
36
56
|
|
37
57
|
def valid?
|
38
|
-
|
39
|
-
|
58
|
+
field_value_mapping
|
59
|
+
|
60
|
+
fields.all? do |field|
|
61
|
+
value = values[field.name.to_sym]
|
62
|
+
field.valid? value
|
40
63
|
end
|
41
64
|
end
|
42
65
|
|
@@ -50,32 +73,24 @@ class ShafClient
|
|
50
73
|
super
|
51
74
|
end
|
52
75
|
|
53
|
-
def valid_field?(field)
|
54
|
-
key = field['name'].to_sym
|
55
|
-
return false unless validate_required(field, key)
|
56
|
-
return true if values[key].nil?
|
57
|
-
return false unless validate_number(field, key)
|
58
|
-
return false unless validate_string(field, key)
|
59
|
-
true
|
60
|
-
end
|
61
|
-
|
62
76
|
private
|
63
77
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
78
|
+
def encoded_payload
|
79
|
+
if content_type&.downcase == 'application/x-www-form-urlencoded'
|
80
|
+
URI.encode_www_form(values)
|
81
|
+
else
|
82
|
+
JSON.generate(values)
|
83
|
+
end
|
69
84
|
end
|
70
85
|
|
71
|
-
def
|
72
|
-
|
73
|
-
values[key].is_a? String
|
86
|
+
def field_names
|
87
|
+
fields.map { |f| f.name.to_sym }
|
74
88
|
end
|
75
89
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
90
|
+
def field_value_mapping
|
91
|
+
field_names.each_with_object({}) do |name, mapping|
|
92
|
+
mapping[name.to_sym] = values[name.to_sym]
|
93
|
+
end
|
79
94
|
end
|
80
95
|
end
|
81
96
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'shaf_client/form'
|
2
|
+
|
3
|
+
class ShafClient
|
4
|
+
class HalForm < Form
|
5
|
+
attr_accessor :target
|
6
|
+
|
7
|
+
content_type 'application/prs.hal-forms+json'
|
8
|
+
|
9
|
+
def title
|
10
|
+
template[:title]
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
attribute(:name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def http_method
|
18
|
+
template[:method].downcase.to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
def content_type
|
22
|
+
template[:contentType]
|
23
|
+
end
|
24
|
+
|
25
|
+
def fields
|
26
|
+
template[:properties].map do |values|
|
27
|
+
Field.new(values.transform_keys(&:to_sym))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def template
|
34
|
+
@template ||= attributes
|
35
|
+
.dig(:_templates, 'default')
|
36
|
+
.transform_keys(&:to_sym)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/shaf_client/link.rb
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
class ShafClient
|
4
4
|
class Link
|
5
|
-
attr_reader :templated
|
6
|
-
|
7
5
|
def self.from(data)
|
8
6
|
if data.is_a? Array
|
9
7
|
data.map { |d| new(href: d['href'], templated: d['templated']) }
|
@@ -17,7 +15,9 @@ class ShafClient
|
|
17
15
|
@templated = !!templated
|
18
16
|
end
|
19
17
|
|
20
|
-
|
18
|
+
def templated?
|
19
|
+
@templated
|
20
|
+
end
|
21
21
|
|
22
22
|
def href
|
23
23
|
@href.dup
|
@@ -26,10 +26,9 @@ class ShafClient
|
|
26
26
|
def resolve_templated(**args)
|
27
27
|
return href unless templated?
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
29
|
+
href
|
30
|
+
.then { |href| resolve_required(href, **args) }
|
31
|
+
.then { |href| resolve_optional(href, **args) }
|
33
32
|
end
|
34
33
|
|
35
34
|
def to_h
|
@@ -38,5 +37,29 @@ class ShafClient
|
|
38
37
|
templated: templated?
|
39
38
|
}
|
40
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def resolve_required(href, **args)
|
44
|
+
String(href).gsub(/{(?!\?)([^}]*)}/) do
|
45
|
+
key = $1.to_sym
|
46
|
+
args.fetch key do
|
47
|
+
raise ArgumentError, "missing keyword: :#{key}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def resolve_optional(href, **args)
|
53
|
+
String(href).gsub(/{\?([^}]*)}/) do
|
54
|
+
values = []
|
55
|
+
$1.split(',').each do |key|
|
56
|
+
next unless args.key? key.to_sym
|
57
|
+
values << "#{key}=#{args[key.to_sym]}"
|
58
|
+
end
|
59
|
+
|
60
|
+
next '' if values.empty?
|
61
|
+
"?#{values.join('&')}"
|
62
|
+
end
|
63
|
+
end
|
41
64
|
end
|
42
65
|
end
|
data/lib/shaf_client/resource.rb
CHANGED
@@ -49,6 +49,21 @@ class ShafClient
|
|
49
49
|
client.get_doc(uri)
|
50
50
|
end
|
51
51
|
|
52
|
+
def get_hal_form(rel)
|
53
|
+
href = link(rel).href
|
54
|
+
uri = rel.to_s
|
55
|
+
if uri.match? %r{:[^/]}
|
56
|
+
curie_name, rel = rel.split(':')
|
57
|
+
curie = curie(curie_name)
|
58
|
+
uri = curie.resolve_templated(rel: rel)
|
59
|
+
end
|
60
|
+
|
61
|
+
headers = {'Accept': 'application/prs.hal-forms+json'}
|
62
|
+
client.get(uri, headers: headers).tap do |form|
|
63
|
+
form.target = href if form.respond_to? :target=
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
52
67
|
def reload!
|
53
68
|
self << get(:self, headers: {'Cache-Control': 'no-cache'})
|
54
69
|
end
|
@@ -3,12 +3,8 @@ require 'shaf_client/error'
|
|
3
3
|
class ShafClient
|
4
4
|
class ResourceMapper
|
5
5
|
class << self
|
6
|
-
def all
|
7
|
-
@all ||= {}
|
8
|
-
end
|
9
|
-
|
10
6
|
def for(content_type)
|
11
|
-
|
7
|
+
mapping[content_type&.to_sym].tap do |clazz|
|
12
8
|
next if clazz
|
13
9
|
raise UnSupportedContentType,
|
14
10
|
"Can't handle Content-Type: #{content_type}"
|
@@ -16,11 +12,17 @@ class ShafClient
|
|
16
12
|
end
|
17
13
|
|
18
14
|
def register(content_type, clazz)
|
19
|
-
|
15
|
+
mapping[content_type&.to_sym] = clazz
|
20
16
|
end
|
21
17
|
|
22
18
|
def default=(clazz)
|
23
|
-
|
19
|
+
mapping.default = clazz
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def mapping
|
25
|
+
@mapping ||= {}
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'shaf_client/form'
|
2
|
+
|
3
|
+
class ShafClient
|
4
|
+
class ShafForm < Form
|
5
|
+
|
6
|
+
profile 'shaf-form'
|
7
|
+
|
8
|
+
def title
|
9
|
+
attribute(:title)
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
attribute(:name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def target
|
17
|
+
attribute(:href)
|
18
|
+
end
|
19
|
+
|
20
|
+
def http_method
|
21
|
+
attribute(:method).downcase.to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def content_type
|
25
|
+
attribute(:type)
|
26
|
+
end
|
27
|
+
|
28
|
+
def fields
|
29
|
+
attribute(:fields).map do |values|
|
30
|
+
Field.new(values.transform_keys(&:to_sym))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
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.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sammy Henningsson
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
ZMhjYR7sRczGJx+GxGU2EaR0bjRsPVlC4ywtFxoOfRG3WaJcpWGEoAoMJX6Z0bRv
|
31
31
|
M40=
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2019-09-
|
33
|
+
date: 2019-09-20 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: faraday
|
@@ -106,11 +106,14 @@ files:
|
|
106
106
|
- lib/shaf_client/curie.rb
|
107
107
|
- lib/shaf_client/empty_resource.rb
|
108
108
|
- lib/shaf_client/error.rb
|
109
|
+
- lib/shaf_client/field.rb
|
109
110
|
- lib/shaf_client/form.rb
|
111
|
+
- lib/shaf_client/hal_form.rb
|
110
112
|
- lib/shaf_client/link.rb
|
111
113
|
- lib/shaf_client/middleware/redirect.rb
|
112
114
|
- lib/shaf_client/resource.rb
|
113
115
|
- lib/shaf_client/resource_mapper.rb
|
116
|
+
- lib/shaf_client/shaf_form.rb
|
114
117
|
- lib/shaf_client/unknown_resource.rb
|
115
118
|
homepage: https://github.com/sammyhenningsson/shaf_client
|
116
119
|
licenses:
|
metadata.gz.sig
CHANGED
Binary file
|