shaf 1.5.2 → 1.6.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -1
- data/lib/shaf/helpers/json_html.rb +58 -18
- data/lib/shaf/helpers/payload.rb +13 -8
- data/lib/shaf/responder/hal.rb +1 -7
- data/lib/shaf/responder/hal_serializable.rb +13 -3
- data/lib/shaf/responder/html.rb +35 -6
- data/lib/shaf/version.rb +1 -1
- data/templates/frontend/assets/css/main.css +33 -1
- data/templates/frontend/views/headers.erb +20 -0
- data/templates/frontend/views/layout.erb +7 -1
- data/templates/frontend/views/payload.erb +1 -0
- data/upgrades/1.6.0.tar.gz +0 -0
- metadata +4 -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: bd5e02da6f878d5f9e0ef2e4d3adb641e9ea34362c943cff5a9e94d93ffaad26
|
4
|
+
data.tar.gz: 565dd3872f4b46a48955b94ebbb6324472ec6293bf1f7ead551a55fdc5bd4d4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 129bf19d6c7ff6ff0f1df840078fbba5df8e47045e69a5b3a3e40ebdc2680f46ad36dc3c4660f8dd8ba5187368fa3b0ecdb503b0575def9f1403ed0d6e743935
|
7
|
+
data.tar.gz: c4fa82f52be8f910f40cebe13b0c5df52239a780788d7d083bc6f969cbfb02c9d72a4aa1fa1e2dce6cc23013be92e9d0eaacc849beaf9e05decacc34ccb9ed3d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
�u�
|
2
|
+
�� %5,2kc����S�Py�S��I�����
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shaf
|
2
4
|
module JsonHtml
|
5
|
+
STRUCTURAL_PATTERN = /^[\[\]\{\}:,]$/.freeze
|
3
6
|
|
4
7
|
def json2html(json)
|
5
8
|
as_html JSON.parse(json)
|
@@ -18,7 +21,7 @@ module Shaf
|
|
18
21
|
when Hash
|
19
22
|
html_hash(obj, indent, pre_indent)
|
20
23
|
else
|
21
|
-
html_scalar(obj,
|
24
|
+
html_scalar(obj, pre_indent)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
@@ -28,41 +31,78 @@ module Shaf
|
|
28
31
|
end
|
29
32
|
|
30
33
|
<<~EOS.chomp
|
31
|
-
#{pre_indent}
|
32
|
-
#{array_of_strings.join(
|
33
|
-
#{indentation(indent)}
|
34
|
+
#{pre_indent}#{span '['}
|
35
|
+
#{array_of_strings.join(item_separator)}
|
36
|
+
#{indentation(indent)}#{span ']'}
|
34
37
|
EOS
|
35
38
|
end
|
36
39
|
|
37
40
|
def html_hash(h, indent, pre_indent)
|
38
41
|
<<~EOS.chomp
|
39
|
-
#{pre_indent}
|
40
|
-
#{h.map { |k,v| sub_hash(k,v, indent + 1) }.join(
|
41
|
-
#{indentation(indent)}
|
42
|
+
#{pre_indent}#{span '{'}
|
43
|
+
#{h.map { |k,v| sub_hash(k,v, indent + 1) }.join(item_separator)}#{item_separator}
|
44
|
+
#{indentation(indent)}#{span '}'}
|
42
45
|
EOS
|
43
46
|
end
|
44
47
|
|
45
|
-
def html_scalar(s,
|
46
|
-
|
47
|
-
format "%s%s%s%s", pre_indent, q, s, q
|
48
|
+
def html_scalar(s, pre_indent)
|
49
|
+
format '%s%s', pre_indent, span(s)
|
48
50
|
end
|
49
51
|
|
50
52
|
def sub_hash(key, value, indent)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
left_side = format '%s%s%s ', indentation(indent), quoted(key), span(':')
|
54
|
+
left_side +
|
55
|
+
if key.to_s == 'href'
|
56
|
+
link(value)
|
57
|
+
else
|
58
|
+
to_html(value, indent: indent)
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
62
|
def indentation(i)
|
59
63
|
" " * i
|
60
64
|
end
|
61
65
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
66
|
+
def quoted(obj)
|
67
|
+
case obj
|
68
|
+
when STRUCTURAL_PATTERN
|
69
|
+
obj
|
70
|
+
when String, Symbol
|
71
|
+
format '"%s"', obj
|
72
|
+
when NilClass
|
73
|
+
'null'
|
74
|
+
else
|
75
|
+
obj
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def link(href)
|
80
|
+
format '<a href="%s">%s</a>', href, quoted(href)
|
65
81
|
end
|
66
82
|
|
83
|
+
def span(value)
|
84
|
+
clazz = span_class(value)
|
85
|
+
value = quoted(value)
|
86
|
+
format '<span class="%s">%s</span>', clazz, value
|
87
|
+
end
|
88
|
+
|
89
|
+
def span_class(obj)
|
90
|
+
case obj
|
91
|
+
when TrueClass, FalseClass
|
92
|
+
'boolean'
|
93
|
+
when NilClass
|
94
|
+
'null'
|
95
|
+
when Numeric
|
96
|
+
'number'
|
97
|
+
when STRUCTURAL_PATTERN
|
98
|
+
'structural'
|
99
|
+
else
|
100
|
+
'string'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def item_separator
|
105
|
+
"#{span ','}\n"
|
106
|
+
end
|
67
107
|
end
|
68
108
|
end
|
data/lib/shaf/helpers/payload.rb
CHANGED
@@ -6,6 +6,7 @@ require 'shaf/responder'
|
|
6
6
|
module Shaf
|
7
7
|
module Payload
|
8
8
|
EXCLUDED_FORM_PARAMS = ['captures', 'splat'].freeze
|
9
|
+
NO_VALUE = Object.new.freeze
|
9
10
|
|
10
11
|
private
|
11
12
|
|
@@ -61,8 +62,8 @@ module Shaf
|
|
61
62
|
name == '_method'
|
62
63
|
end
|
63
64
|
|
64
|
-
def profile(value =
|
65
|
-
return @profile
|
65
|
+
def profile(value = NO_VALUE)
|
66
|
+
return @profile if value == NO_VALUE
|
66
67
|
@profile = value
|
67
68
|
end
|
68
69
|
|
@@ -81,15 +82,13 @@ module Shaf
|
|
81
82
|
status ||= resource.respond_to?(:http_status) ? resource.http_status : 200
|
82
83
|
status(status)
|
83
84
|
|
84
|
-
kwargs.merge!(
|
85
|
-
|
86
|
-
serializer: serializer,
|
87
|
-
collection: collection
|
88
|
-
)
|
85
|
+
kwargs.merge!(serializer: serializer, collection: collection)
|
86
|
+
kwargs[:profile] ||= profile
|
89
87
|
|
90
88
|
log.info "#{request.request_method} #{request.path_info} => #{status}"
|
91
89
|
payload = Responder.for(request, resource).call(self, resource, preload: preload, **kwargs)
|
92
90
|
add_cache_headers(payload, kwargs)
|
91
|
+
|
93
92
|
payload
|
94
93
|
rescue StandardError => err
|
95
94
|
log.error "Failure: #{err.message}\n#{err.backtrace}"
|
@@ -103,10 +102,16 @@ module Shaf
|
|
103
102
|
|
104
103
|
def add_cache_headers(payload, kwargs)
|
105
104
|
return unless kwargs.delete(:http_cache) { Settings.http_cache }
|
105
|
+
|
106
|
+
chksum, kind = etag_for(payload)
|
107
|
+
etag(chksum, kind: kind) if chksum
|
108
|
+
end
|
109
|
+
|
110
|
+
def etag_for(payload)
|
106
111
|
return if payload.nil? || payload.empty?
|
107
112
|
|
108
113
|
sha1 = Digest::SHA1.hexdigest payload
|
109
|
-
|
114
|
+
[sha1, :weak] # Weak or Strong??
|
110
115
|
end
|
111
116
|
end
|
112
117
|
end
|
data/lib/shaf/responder/hal.rb
CHANGED
@@ -9,7 +9,7 @@ module Shaf
|
|
9
9
|
mime_type :hal, 'application/hal+json'
|
10
10
|
|
11
11
|
def body
|
12
|
-
@body ||=
|
12
|
+
@body ||= generate_json
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
@@ -19,12 +19,6 @@ module Shaf
|
|
19
19
|
type = "#{type};profile=#{profile}" if profile
|
20
20
|
type
|
21
21
|
end
|
22
|
-
|
23
|
-
def profile
|
24
|
-
return unless serializer
|
25
|
-
|
26
|
-
@profile ||= options[:profile] || serializer.semantic_profile
|
27
|
-
end
|
28
22
|
end
|
29
23
|
end
|
30
24
|
end
|
@@ -6,9 +6,7 @@ module Shaf
|
|
6
6
|
module HalSerializable
|
7
7
|
def lookup_rel(rel, response)
|
8
8
|
hal = response.serialized_hash
|
9
|
-
|
10
|
-
|
11
|
-
links = hal.dig(:_links, rel.to_sym)
|
9
|
+
links = hal&.dig(:_links, rel.to_sym)
|
12
10
|
return [] unless links
|
13
11
|
|
14
12
|
links = [links] unless links.is_a? Array
|
@@ -49,6 +47,18 @@ module Shaf
|
|
49
47
|
|
50
48
|
@serialized_hash
|
51
49
|
end
|
50
|
+
|
51
|
+
def profile
|
52
|
+
@profile ||= options[:profile]
|
53
|
+
return unless @profile || serializer
|
54
|
+
|
55
|
+
@profile ||= serializer.semantic_profile
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_json
|
59
|
+
# FIXME: change to Oj??
|
60
|
+
JSON.generate(serialized_hash)
|
61
|
+
end
|
52
62
|
end
|
53
63
|
end
|
54
64
|
end
|
data/lib/shaf/responder/html.rb
CHANGED
@@ -8,12 +8,41 @@ module Shaf
|
|
8
8
|
mime_type :html
|
9
9
|
|
10
10
|
def body
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
locals = variables
|
12
|
+
|
13
|
+
template =
|
14
|
+
case resource
|
15
|
+
when Formable::Form
|
16
|
+
locals.merge!(form: resource)
|
17
|
+
:form
|
18
|
+
else
|
19
|
+
:payload
|
20
|
+
end
|
21
|
+
|
22
|
+
controller.erb(template, locals: locals)
|
23
|
+
end
|
24
|
+
|
25
|
+
def variables
|
26
|
+
{
|
27
|
+
request_headers: request_headers,
|
28
|
+
response_headers: response_headers,
|
29
|
+
serialized: serialized_hash
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def request_headers
|
34
|
+
controller.request_headers
|
35
|
+
end
|
36
|
+
|
37
|
+
def response_headers
|
38
|
+
etag, kind = controller.send(:etag_for, generate_json)
|
39
|
+
prefix = kind == :weak ? 'W/' : ''
|
40
|
+
etag = %Q{#{prefix}"#{etag}"}
|
41
|
+
|
42
|
+
type = Hal.mime_type
|
43
|
+
type = "#{type};profile=#{profile}" if profile
|
44
|
+
|
45
|
+
controller.headers.merge('Content-Type' => type, 'ETag' => etag)
|
17
46
|
end
|
18
47
|
end
|
19
48
|
end
|
data/lib/shaf/version.rb
CHANGED
@@ -16,10 +16,18 @@ ul {
|
|
16
16
|
list-style-type: none;
|
17
17
|
}
|
18
18
|
|
19
|
+
td {
|
20
|
+
min-width: 20em;
|
21
|
+
}
|
22
|
+
|
19
23
|
pre {
|
20
24
|
margin: 0;
|
21
25
|
}
|
22
26
|
|
27
|
+
main {
|
28
|
+
padding-bottom: 8em;
|
29
|
+
}
|
30
|
+
|
23
31
|
.container {
|
24
32
|
display: flex;
|
25
33
|
flex-direction: row;
|
@@ -33,6 +41,10 @@ pre {
|
|
33
41
|
height: 100%;
|
34
42
|
}
|
35
43
|
|
44
|
+
.headers {
|
45
|
+
margin-bottom: 2em;
|
46
|
+
}
|
47
|
+
|
36
48
|
.hal-form {
|
37
49
|
height: auto;
|
38
50
|
display: flex;
|
@@ -60,11 +72,31 @@ pre {
|
|
60
72
|
min-height: 100%;
|
61
73
|
height: auto;
|
62
74
|
overflow: auto;
|
63
|
-
background-color: #
|
75
|
+
background-color: #e0e0e0;
|
64
76
|
display: flex;
|
65
77
|
flex-direction: row;
|
66
78
|
justify-content: flex-start;
|
67
79
|
align-items: flex-start;
|
68
80
|
padding: 1em;
|
81
|
+
border-radius: 20px;
|
82
|
+
}
|
83
|
+
|
84
|
+
span.boolean {
|
85
|
+
color: #0277BD;
|
69
86
|
}
|
70
87
|
|
88
|
+
span.null {
|
89
|
+
color: #757575;
|
90
|
+
}
|
91
|
+
|
92
|
+
span.number {
|
93
|
+
color: #3F51B5;
|
94
|
+
}
|
95
|
+
|
96
|
+
span.structural {
|
97
|
+
color: black;
|
98
|
+
}
|
99
|
+
|
100
|
+
span.string {
|
101
|
+
color: #43A047;
|
102
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<section class="section headers">
|
3
|
+
<h3><%= title %></h3>
|
4
|
+
<table class="hal-payload">
|
5
|
+
<% headers.each do |key, value| %>
|
6
|
+
<tr>
|
7
|
+
<td><%= key %></td>
|
8
|
+
<td><%= value %></td>
|
9
|
+
</tr>
|
10
|
+
<% end %>
|
11
|
+
</table>
|
12
|
+
<ul>
|
13
|
+
<% notes.each do |note| %>
|
14
|
+
<li>
|
15
|
+
<p><sub><%= note %></sub></p>
|
16
|
+
</li>
|
17
|
+
<% end %>
|
18
|
+
</ul>
|
19
|
+
</section>
|
20
|
+
</div>
|
@@ -6,6 +6,12 @@
|
|
6
6
|
<link rel="stylesheet" type="text/css" href="/css/main.css">
|
7
7
|
</head>
|
8
8
|
<body>
|
9
|
-
|
9
|
+
<div class="main-container">
|
10
|
+
<main>
|
11
|
+
<%= yield %>
|
12
|
+
</main>
|
13
|
+
<%= erb :headers, locals: {title: 'Request headers', headers: request_headers, notes: []} %>
|
14
|
+
<%= erb :headers, locals: {title: 'Response headers', headers: response_headers, notes: ["This is an example of a response to a request with Accept: #{response_headers['Content-Type']}. YMMV"]} %>
|
15
|
+
</div>
|
10
16
|
</body>
|
11
17
|
</html>
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shaf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.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: 2020-
|
33
|
+
date: 2020-04-21 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: minitest
|
@@ -328,6 +328,7 @@ files:
|
|
328
328
|
- templates/config/settings.yml
|
329
329
|
- templates/frontend/assets/css/main.css
|
330
330
|
- templates/frontend/views/form.erb
|
331
|
+
- templates/frontend/views/headers.erb
|
331
332
|
- templates/frontend/views/layout.erb
|
332
333
|
- templates/frontend/views/payload.erb
|
333
334
|
- templates/spec/integration/root_spec.rb
|
@@ -345,6 +346,7 @@ files:
|
|
345
346
|
- upgrades/1.3.0.tar.gz
|
346
347
|
- upgrades/1.4.0.tar.gz
|
347
348
|
- upgrades/1.5.0.tar.gz
|
349
|
+
- upgrades/1.6.0.tar.gz
|
348
350
|
homepage:
|
349
351
|
licenses:
|
350
352
|
- MIT
|
metadata.gz.sig
CHANGED
Binary file
|