deprecation_collector 0.2.0 → 0.4.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.
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeprecationCollector
4
+ class Web
5
+ module Router
6
+ HTTP_METHODS = %w[GET HEAD POST PUT PATCH DELETE].freeze
7
+ HTTP_METHODS.each do |http_method|
8
+ const_set http_method, http_method
9
+ class_eval <<~RUBY, __FILE__, __LINE__+1
10
+ def #{http_method.downcase}(path, &block)
11
+ route(#{http_method}, path, &block)
12
+ end
13
+ RUBY
14
+ end
15
+
16
+ def root(&block)
17
+ route(GET, '/', &block)
18
+ end
19
+
20
+ def route(method, path, &block)
21
+ ((@routes ||= {})[method] ||= []) << Route.new(method, path, block)
22
+ end
23
+
24
+ def helpers(mod = nil, &block)
25
+ return ActionContext.class_eval(&block) if block
26
+ ActionContext.send(:include, mod)
27
+ end
28
+
29
+
30
+ ROUTE_PARAMS = "rack.route_params"
31
+ PATH_INFO = "PATH_INFO"
32
+
33
+ def match(env)
34
+ request = ::Rack::Request.new(env)
35
+ request_method = request.request_method
36
+ request_method = request.params["_method"] if request.params["_method"]
37
+
38
+ path_info = ::Rack::Utils.unescape env[PATH_INFO]
39
+ path_info = "/" if path_info == "" # some buggy servers may pass empty root path
40
+
41
+ @routes[request_method.upcase]&.find do |route|
42
+ params = route.match(request_method, path_info)
43
+ next unless params
44
+ env[ROUTE_PARAMS] = params
45
+ break ActionContext.new(request, &route.block)
46
+ end
47
+ end
48
+
49
+ def call(env, application=nil)
50
+ action = match(env)
51
+ unless action
52
+ return [
53
+ 404,
54
+ {"content-type" => "text/plain", "x-cascade" => "pass"},
55
+ ["Not Found #{env["REQUEST_METHOD"].inspect} #{env[PATH_INFO].inspect}"]
56
+ ]
57
+ end
58
+
59
+ resp = catch(:halt) do
60
+ action.call(env, application)
61
+ ensure
62
+ end
63
+
64
+ return resp if resp.is_a?(Array) # raw rack responses (redirects etc.)
65
+
66
+ # rendered content goes here
67
+ headers = {
68
+ "content-type" => "text/html",
69
+ "cache-control" => "private, no-store",
70
+ # TODO:
71
+ # "content-language" => action.locale,
72
+ # "content-security-policy" => CSP_HEADER
73
+ }
74
+ # we'll let Rack calculate Content-Length for us.
75
+ [200, headers, [resp]]
76
+ end
77
+
78
+ class Route
79
+ attr_accessor :request_method, :pattern, :block
80
+
81
+ NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^.:$\/]+)/
82
+
83
+ def initialize(request_method, pattern, block)
84
+ @request_method = request_method
85
+ @pattern = pattern
86
+ @block = block
87
+ end
88
+
89
+ def matcher
90
+ @matcher ||= compile_matcher
91
+ end
92
+
93
+ def compile_matcher
94
+ return pattern unless pattern.match?(NAMED_SEGMENTS_PATTERN)
95
+ regex_pattern = pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)') # /some/:id => /some/(?<id>[^$/]+)
96
+
97
+ Regexp.new("\\A#{regex_pattern}\\Z")
98
+ end
99
+
100
+ def match(request_method, path)
101
+ case matcher
102
+ when String
103
+ {} if path == matcher
104
+ else
105
+ path_match = path.match(matcher)
106
+ path_match&.named_captures&.transform_keys(&:to_sym)
107
+ end
108
+ end
109
+ end
110
+
111
+ class ActionContext
112
+ attr_accessor :request
113
+
114
+ def initialize(request, &block)
115
+ @request = request
116
+ @block = block
117
+ end
118
+
119
+ def call(env, application)
120
+ @web = application.web
121
+ instance_exec(&@block)
122
+ end
123
+
124
+ def env
125
+ request.env
126
+ end
127
+
128
+ def route_params
129
+ env[Router::ROUTE_PARAMS]
130
+ end
131
+
132
+ def params
133
+ @params ||= Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
134
+ .merge!(request.params)
135
+ .merge!(route_params.transform_keys(&:to_s))
136
+ end
137
+
138
+ def halt(res, content=nil)
139
+ throw :halt, [res, {"content-type" => "text/plain"}, [content || res.to_s]]
140
+ end
141
+
142
+ def redirect_to(location)
143
+ throw :halt, [302, {"location" => "#{request.base_url}#{location}"}, []]
144
+ end
145
+
146
+ def render(plain: nil, html: nil, json: nil, erb: nil, slim: nil, status: 200, locals: nil, layout: 'layout.html.slim')
147
+ raise ArgumentError, "provide exactly one render format" unless [plain, html, json, erb, slim].compact.size == 1
148
+
149
+ if json
150
+ json = JSON.generate(json) unless json.is_a?(String)
151
+ return [status, {"content-type" => "application/json"}, [json]]
152
+ end
153
+ return [status, {"content-type" => "text/plain"}, [plain.to_s]] if plain
154
+
155
+ _define_locals(locals) if locals
156
+ template = "#{erb}.erb" if erb
157
+ template = "#{slim}.slim" if slim
158
+ html = render_template(template) if template
159
+ html = render_template(layout) { html } if layout
160
+
161
+ color_scheme_headers = {
162
+ 'Accept-CH' => 'Sec-CH-Prefers-Color-Scheme',
163
+ 'Vary' => 'Sec-CH-Prefers-Color-Scheme',
164
+ 'Critical-CH' => 'Sec-CH-Prefers-Color-Scheme'
165
+ }
166
+
167
+ return [status, {"content-type" => "text/html"}.merge(color_scheme_headers), [html.to_s]] if html
168
+ end
169
+
170
+ VIEW_PATH = "#{__dir__}/views"
171
+
172
+ def render_template(template, &block)
173
+ original_template_name = File.join(VIEW_PATH, template.to_s)
174
+ template = template.gsub(/\.slim\z/, '.template.rb')
175
+ template_method_name = "_template_#{template.gsub(/[^\w]/, '_')}"
176
+ template_filename = File.join(VIEW_PATH, template.to_s)
177
+
178
+ if ENV['DEPRECATION_COLLECTOR_RELOAD_WEB_TEMPLATES']
179
+ require 'slim'
180
+ puts "Recompiling #{original_template_name}"
181
+ ActionContext.class_eval { undef_method(template_method_name) } if respond_to?(template_method_name)
182
+ if original_template_name.end_with?('.slim')
183
+ File.write(template_filename, Slim::Template.new(original_template_name).precompiled_template)
184
+ end
185
+ end
186
+
187
+ unless respond_to?(template_method_name)
188
+ src = File.read(template_filename)
189
+ src = ERB.new(src).src if template_filename.end_with?('.erb')
190
+ ActionContext.class_eval <<-RUBY, template_filename.gsub(/\.template\.rb\z/, '.slim'), 1
191
+ def #{template_method_name}; #{src}
192
+ end
193
+ RUBY
194
+ end
195
+
196
+ send(template_method_name, &block)
197
+ end
198
+
199
+ private
200
+ def _define_locals(locals)
201
+ locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include?(k) }
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,52 @@
1
+
2
+ begin
3
+ require 'cgi/escape'
4
+ rescue LoadError
5
+ end
6
+
7
+ module Temple
8
+ # @api public
9
+ module Utils
10
+ extend self
11
+
12
+ # Returns an escaped copy of `html`.
13
+ # Strings which are declared as html_safe are not escaped.
14
+ #
15
+ # @param html [String] The string to escape
16
+ # @return [String] The escaped string
17
+ def escape_html_safe(html)
18
+ s = html.to_s
19
+ s.html_safe? || html.html_safe? ? s : escape_html(s)
20
+ end
21
+
22
+ if defined?(CGI.escapeHTML)
23
+ # Returns an escaped copy of `html`.
24
+ #
25
+ # @param html [String] The string to escape
26
+ # @return [String] The escaped string
27
+ def escape_html(html)
28
+ CGI.escapeHTML(html.to_s)
29
+ end
30
+ else
31
+ # Used by escape_html
32
+ # @api private
33
+ ESCAPE_HTML = {
34
+ '&' => '&amp;',
35
+ '"' => '&quot;',
36
+ '\'' => '&#39;',
37
+ '<' => '&lt;',
38
+ '>' => '&gt;'
39
+ }.freeze
40
+
41
+ ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
42
+
43
+ # Returns an escaped copy of `html`.
44
+ #
45
+ # @param html [String] The string to escape
46
+ # @return [String] The escaped string
47
+ def escape_html(html)
48
+ html.to_s.gsub(ESCAPE_HTML_PATTERN, ESCAPE_HTML)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ _buf = ''; _buf << ("<header><h1>Import dump</h1></header><main><form".freeze);
2
+ ;
3
+ ;
4
+ ;
5
+ ; _slim_codeattributes1 = import_deprecations_path; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" action=\"\"".freeze); else; _buf << (" action=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" enctype=\"multipart/form-data\" method=\"post\"><div class=\"mb-3\"><label class=\"form-label\" for=\"file\">Choose a JSON file to upload:</label> <input class=\"form-comtrol\" id=\"file\" name=\"file\" type=\"file\" /></div><div class=\"mb-3\"><button class=\"btn btn-primary\" type=\"submit\">Upload</button> <a class=\"btn btn-secondary\"".freeze);
6
+ ;
7
+ ;
8
+ ;
9
+ ;
10
+ ;
11
+ ; _slim_codeattributes2 = dump_deprecations_path; if _slim_codeattributes2; if _slim_codeattributes2 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes2))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Dump</a> <a class=\"btn btn-secondary\"".freeze);
12
+ ; _slim_codeattributes3 = deprecations_path; if _slim_codeattributes3; if _slim_codeattributes3 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes3))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Back</a> </div></form></main>".freeze);
13
+ ; _buf
@@ -0,0 +1,111 @@
1
+ _buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecations</h1><a class=\"btn btn-primary\" data-method=\"post\"".freeze);
2
+ ;
3
+ ;
4
+ ; _slim_codeattributes1 = deprecation_path(:trigger); if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">Trigger a couple</a> <a class=\"btn btn-danger\" data-confirm=\"Sure?\" data-method=\"delete\"".freeze);
5
+ ; _slim_codeattributes2 = deprecation_path(:all); if _slim_codeattributes2; if _slim_codeattributes2 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes2))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\"><i class=\"bi bi-trash\"></i>Delete all </a> ".freeze);
6
+ ;
7
+ ;
8
+ ;
9
+ ; if DeprecationCollector.instance.enabled_in_redis?;
10
+ ;
11
+ ;
12
+ ;
13
+ ; _buf << ("<a class=\"btn btn-danger\" data-confirm=\"Sure? Will need to restart workers after enabling\" data-method=\"delete\"".freeze); _slim_codeattributes3 = disable_deprecations_path; if _slim_codeattributes3; if _slim_codeattributes3 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes3))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">Disable</a> ".freeze);
14
+ ; else;
15
+ ;
16
+ ;
17
+ ; _buf << ("<a class=\"btn btn-secondary\" data-method=\"post\"".freeze); _slim_codeattributes4 = enable_deprecations_path; if _slim_codeattributes4; if _slim_codeattributes4 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes4))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">Turn on (after workers restart)</a> ".freeze);
18
+ ;
19
+ ; end; _buf << ("</header><main><table class=\"table table-striped\"><tr><th>Count</th><th>Message</th><th>Location</th><th>Ruby/Rails</th></tr>".freeze);
20
+ ;
21
+ ;
22
+ ;
23
+ ;
24
+ ;
25
+ ;
26
+ ;
27
+ ; total = 0;
28
+ ; @deprecations.each do |deprecation|;
29
+ ; total += 1;
30
+ ; _buf << ("<tr".freeze); _slim_codeattributes5 = deprecation[:digest]; if _slim_codeattributes5; if _slim_codeattributes5 == true; _buf << (" data-digest=\"\"".freeze); else; _buf << (" data-digest=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes5))).to_s); _buf << ("\"".freeze); end; end; _buf << ("><td><a".freeze);
31
+ ;
32
+ ; _slim_codeattributes6 = deprecation_path(deprecation[:digest]); if _slim_codeattributes6; if _slim_codeattributes6 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes6))).to_s); _buf << ("\"".freeze); end; end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation[:count]))).to_s);
33
+ ; _buf << ("</a><br />".freeze);
34
+ ; deprecation_tags(deprecation).each_pair do |tag, cls|;
35
+ ; _buf << ("<div".freeze); _temple_html_attributeremover1 = ''; _temple_html_attributemerger1 = []; _temple_html_attributemerger1[0] = "badge"; _temple_html_attributemerger1[1] = ''; _slim_codeattributes7 = cls; if Array === _slim_codeattributes7; _slim_codeattributes7 = _slim_codeattributes7.flatten; _slim_codeattributes7.map!(&:to_s); _slim_codeattributes7.reject!(&:empty?); _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7.join(" ")))).to_s); else; _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7))).to_s); end; _temple_html_attributemerger1[1]; _temple_html_attributeremover1 << ((_temple_html_attributemerger1.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover1; if !_temple_html_attributeremover1.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover1).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((tag))).to_s);
36
+ ;
37
+ ; _buf << ("</div> ".freeze); end; _buf << ("</td><td>".freeze);
38
+ ;
39
+ ; msg = deprecation[:message]
40
+ delete_prefixes = Gem.path + [defined?(Rails) && Rails.root.to_s].compact
41
+ delete_prefixes.each { |path| msg.gsub!(path, '') }
42
+ msg.delete_prefix! deprecation[:gem_traceline].gsub(/:in .+/, ':') if deprecation[:gem_traceline]
43
+ msg.delete_prefix! deprecation[:app_traceline].gsub(/:in .+/, ':') if deprecation[:app_traceline]
44
+ msg.strip!
45
+ msg.delete_prefix!("DEPRECATION WARNING: ")
46
+ msg.delete_prefix!("warning: ")
47
+ ;
48
+ ; if msg.lines.size > 2;
49
+ ; _buf << ("<pre class=\"pre-scrollable p-1\" style=\"overflow: auto; max-width: 700px; max-height: 200px; font-size: 11px\"><code>".freeze);
50
+ ; _buf << ((::Temple::Utils.escape_html((msg))).to_s);
51
+ ; _buf << ("</code></pre>".freeze); else;
52
+ ; _buf << ("<div class=\"small\">".freeze); _buf << ((::Temple::Utils.escape_html((msg))).to_s);
53
+ ; _buf << ("</div>".freeze); end; if deprecation.dig(:notes, :comment);
54
+ ; _buf << ((::Temple::Utils.escape_html((deprecation.dig(:notes, :comment)))).to_s);
55
+ ;
56
+ ; end; if deprecation.dig(:context, :action);
57
+ ; _buf << ("<div class=\"small controller\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation.dig(:context, :action)))).to_s);
58
+ ; _buf << ("</div>".freeze); elsif deprecation.dig(:context, :params, :controller);
59
+ ; _buf << ("<div class=\"small controller\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation.dig(:context, :params).slice(:controller, :action).values.join('#')))).to_s);
60
+ ;
61
+ ; _buf << ("</div>".freeze); end; _buf << ("</td><td class=\"small\">".freeze);
62
+ ; if deprecation[:gem_traceline];
63
+ ; _buf << ("<div class=\"gem_location\">".freeze);
64
+ ; location, function = deprecation[:gem_traceline].split(':in `', 2);
65
+ ; full_gemname = location.delete_prefix('/gems/').gsub(%r{/.*}, '');
66
+ ; location_in_gem = location.delete_prefix("/gems/#{full_gemname}/");
67
+ ; _buf << ("<i>".freeze); _buf << ((::Temple::Utils.escape_html((full_gemname))).to_s);
68
+ ; _buf << ("</i> <code class=\"code_location\"".freeze); _slim_codeattributes8 = location_in_gem; if _slim_codeattributes8; if _slim_codeattributes8 == true; _buf << (" data-copy-value=\"\"".freeze); else; _buf << (" data-copy-value=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes8))).to_s); _buf << ("\"".freeze); end; end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((location_in_gem.delete_prefix('lib/')))).to_s);
69
+ ; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
70
+ ; _buf << ("</i></div>".freeze); end; if deprecation[:app_traceline];
71
+ ; _buf << ("<div class=\"app_location\">".freeze);
72
+ ; location, function = deprecation[:app_traceline].split(':in `', 2);
73
+ ; _buf << ("<code class=\"code_location\">".freeze); _buf << ((::Temple::Utils.escape_html((location))).to_s);
74
+ ; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
75
+ ; _buf << ("</i></div>".freeze); end; _buf << ("</td><td><div class=\"small ruby\">".freeze);
76
+ ; _buf << ((::Temple::Utils.escape_html((deprecation[:ruby_version]))).to_s);
77
+ ; _buf << ("</div><div class=\"small rails\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation[:rails_version]))).to_s);
78
+ ;
79
+ ; _buf << ("</div><a data-confirm=\"Delete?\" data-method=\"delete\"".freeze); _slim_codeattributes9 = deprecation_path(deprecation[:digest]); if _slim_codeattributes9; if _slim_codeattributes9 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes9))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\" title=\"Delete\"><i class=\"bi bi-trash\"></i></a></td></tr>".freeze);
80
+ ;
81
+ ; end; if total.zero?;
82
+ ; _buf << ("<tr><td".freeze);
83
+ ; _slim_codeattributes10 = 4; if _slim_codeattributes10; if _slim_codeattributes10 == true; _buf << (" colspan=\"\"".freeze); else; _buf << (" colspan=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes10))).to_s); _buf << ("\"".freeze); end; end; _buf << ("><p>Looks like there're no deprecations (or workers have not yet wrote to redis)</p><p>You can try <a data-method=\"post\"".freeze);
84
+ ;
85
+ ;
86
+ ;
87
+ ; _slim_codeattributes11 = deprecation_path(:trigger); if _slim_codeattributes11; if _slim_codeattributes11 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes11))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">trigger a couple</a>".freeze);
88
+ ; if import_enabled?;
89
+ ; _buf << (", or <a".freeze);
90
+ ; _slim_codeattributes12 = import_deprecations_path; if _slim_codeattributes12; if _slim_codeattributes12 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes12))).to_s); _buf << ("\"".freeze); end; end; _buf << (">import</a> ".freeze);
91
+ ;
92
+ ;
93
+ ; end; _buf << ("</p></td></tr>".freeze); end; _buf << ("</table></main><footer>".freeze);
94
+ ; if total > 3;
95
+ ; _buf << ((::Temple::Utils.escape_html((total))).to_s);
96
+ ; _buf << (" deprecations ".freeze);
97
+ ; end; _buf << ("</footer><style>.code_location {\n cursor: pointer;\n}</style><script>document.querySelectorAll('.code_location').forEach(function(elem){\n elem.addEventListener('click', function () {\n let textToCopy = elem.getAttribute('data-copy-value');\n if(!textToCopy) textToCopy = elem.innerText;\n console.log(\"Copying\", textToCopy)\n navigator.clipboard.writeText(textToCopy);\n }, false);\n});</script>".freeze);
98
+ ;
99
+ ;
100
+ ;
101
+ ;
102
+ ;
103
+ ;
104
+ ;
105
+ ;
106
+ ;
107
+ ;
108
+ ;
109
+ ;
110
+ ;
111
+ ; _buf
@@ -0,0 +1,91 @@
1
+ _buf = ''; _buf << ("<!DOCTYPE html><html".freeze);
2
+ ; _slim_codeattributes1 = current_color_theme; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" data-bs-theme=\"\"".freeze); else; _buf << (" data-bs-theme=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" lang=\"en\"><head><meta charset=\"utf-8\" /><meta content=\"IE=edge;chrome=1\" http-equiv=\"X-UA-Compatible\" /><title>".freeze);
3
+ ;
4
+ ;
5
+ ;
6
+ ;
7
+ ; _buf << ((::Temple::Utils.escape_html(("Deprecations"))).to_s);
8
+ ; _buf << ("</title><meta content=\"Deprecation collector ui\" name=\"description\" /><meta content=\"width=device-width\" name=\"viewport\" /><link crossorigin=\"anonymous\" href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css\" integrity=\"sha256-Fu5/PVNGJlC70y4mPEjA6nWVdPz2IMaBrXGQCJEsRho= sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ\" rel=\"stylesheet\" /><link crossorigin=\"anonymous\" href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css\" integrity=\"sha256-4RctOgogjPAdwGbwq+rxfwAmSpZhWaafcZR9btzUk18= sha384-b6lVK+yci+bfDmaY1u0zE8YYJt0TZxLEAFyYSLHId4xoVvsrQu3INevFKo+Xir8e\" rel=\"stylesheet\" /></head><body><div class=\"container-fluid\">".freeze);
9
+ ;
10
+ ;
11
+ ;
12
+ ;
13
+ ;
14
+ ;
15
+ ; _buf << ((yield).to_s);
16
+ ;
17
+ ; _buf << ("</div><script async=\"\" crossorigin=\"anonymous\" integrity=\"sha256-9Mbe9mGA7d+AJbnz0O6CoLGabCbe6JAYnGshvGIADiE=\" src=\"https://cdn.jsdelivr.net/npm/@rails/ujs@7.0.4-3/lib/assets/compiled/rails-ujs.js\"></script><script async=\"\" crossorigin=\"anonymous\" integrity=\"sha256-QucgBAKNM4KKPJHqTfH8e+JON1G/gmPPqtMmBb+wHpc= sha384-Y4oOpwW3duJdCWv5ly8SCFYWqFDsfob/3GkgExXKV4idmbt98QcxXYs9UoXAB7BZ\" src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.min.js\"></script><script>(() => {\n 'use strict'\n\n const storedTheme = localStorage.getItem('theme')\n\n const getPreferredTheme = () => {\n if (storedTheme) { return storedTheme }\n let fromServer = document.documentElement.getAttribute('data-bs-theme')\n if(fromServer) { return fromServer }\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n\n const setTheme = function (theme) {\n if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n document.documentElement.setAttribute('data-bs-theme', 'dark')\n } else {\n document.documentElement.setAttribute('data-bs-theme', theme)\n }\n }\n\n setTheme(getPreferredTheme())\n\n const showActiveTheme = (theme, focus = false) => {\n const themeSwitcher = document.querySelector('#bd-theme')\n\n if (!themeSwitcher) {\n return\n }\n\n const themeSwitcherText = document.querySelector('#bd-theme-text')\n const activeThemeIcon = document.querySelector('.theme-icon-active use')\n const btnToActive = document.querySelector(`[data-bs-theme-value=\"${theme}\"]`)\n const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')\n\n document.querySelectorAll('[data-bs-theme-value]').forEach(element => {\n element.classList.remove('active')\n element.setAttribute('aria-pressed', 'false')\n })\n\n btnToActive.classList.add('active')\n btnToActive.setAttribute('aria-pressed', 'true')\n activeThemeIcon.setAttribute('href', svgOfActiveBtn)\n const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`\n themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)\n\n if (focus) {\n themeSwitcher.focus()\n }\n }\n\n window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {\n if (storedTheme !== 'light' || storedTheme !== 'dark') {\n setTheme(getPreferredTheme())\n }\n })\n\n window.addEventListener('DOMContentLoaded', () => {\n showActiveTheme(getPreferredTheme())\n\n document.querySelectorAll('[data-bs-theme-value]')\n .forEach(toggle => {\n toggle.addEventListener('click', () => {\n const theme = toggle.getAttribute('data-bs-theme-value')\n localStorage.setItem('theme', theme)\n setTheme(theme)\n showActiveTheme(theme, true)\n })\n })\n })\n})()</script></body></html>".freeze);
18
+ ;
19
+ ;
20
+ ;
21
+ ;
22
+ ;
23
+ ;
24
+ ;
25
+ ;
26
+ ;
27
+ ;
28
+ ;
29
+ ;
30
+ ;
31
+ ;
32
+ ;
33
+ ;
34
+ ;
35
+ ;
36
+ ;
37
+ ;
38
+ ;
39
+ ;
40
+ ;
41
+ ;
42
+ ;
43
+ ;
44
+ ;
45
+ ;
46
+ ;
47
+ ;
48
+ ;
49
+ ;
50
+ ;
51
+ ;
52
+ ;
53
+ ;
54
+ ;
55
+ ;
56
+ ;
57
+ ;
58
+ ;
59
+ ;
60
+ ;
61
+ ;
62
+ ;
63
+ ;
64
+ ;
65
+ ;
66
+ ;
67
+ ;
68
+ ;
69
+ ;
70
+ ;
71
+ ;
72
+ ;
73
+ ;
74
+ ;
75
+ ;
76
+ ;
77
+ ;
78
+ ;
79
+ ;
80
+ ;
81
+ ;
82
+ ;
83
+ ;
84
+ ;
85
+ ;
86
+ ;
87
+ ;
88
+ ;
89
+ ;
90
+ ;
91
+ ; _buf
@@ -0,0 +1,13 @@
1
+ _buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecation</h1><a class=\"btn btn-secondary\"".freeze);
2
+ ;
3
+ ;
4
+ ; _slim_codeattributes1 = deprecations_path; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Back</a> <a class=\"btn btn-danger\" data-confirm=\"Delete?\" data-method=\"delete\"".freeze);
5
+ ; _slim_codeattributes2 = deprecation_path(@deprecation[:digest]); if _slim_codeattributes2; if _slim_codeattributes2 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes2))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\" title=\"Delete\"><span class=\"glyphicon glyphicon-trash insalesicon-trash\"></span>Delete</a> </header><main><div class=\"card p-3\"><pre><code>".freeze);
6
+ ;
7
+ ;
8
+ ;
9
+ ;
10
+ ;
11
+ ;
12
+ ; _buf << ((::Temple::Utils.escape_html((@deprecation.pretty_inspect))).to_s);
13
+ ; _buf << ("</code></pre></div></main>".freeze); _buf
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "rack/content_length"
5
+ require "rack/builder"
6
+
7
+ require_relative 'web/application'
8
+
9
+ class DeprecationCollector
10
+ class Web
11
+ attr_accessor :import_enabled
12
+
13
+ def initialize(import_enabled: nil)
14
+ @import_enabled = import_enabled
15
+ end
16
+
17
+ def self.call(env)
18
+ @app ||= new
19
+ @app.call(env)
20
+ end
21
+
22
+ def call(env)
23
+ app.call(env)
24
+ end
25
+
26
+ def app
27
+ @app ||= build
28
+ end
29
+
30
+ private
31
+ def build
32
+ web = self
33
+ ::Rack::Builder.new do
34
+ # use Rack::Static etc goes here
35
+
36
+ run Web::Application.new(web)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -183,7 +183,19 @@ class DeprecationCollector
183
183
  end
184
184
 
185
185
  def dump
186
- read_each.to_a.to_json
186
+ read_each.to_a.compact.to_json
187
+ end
188
+
189
+ def import_dump(json)
190
+ dump = JSON.parse(json)
191
+ # TODO: some checks
192
+
193
+ digests = dump.map { |dep| dep["digest"] }
194
+ raise 'need digests' unless digests.none?(&:nil?)
195
+
196
+ dump_hash = dump.map { |dep| [dep.delete('digest'), dep] }.to_h
197
+
198
+ @redis.mapped_hmset("deprecations:data", dump_hash.transform_values(&:to_json))
187
199
  end
188
200
 
189
201
  def read_each
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deprecation_collector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasily Fedoseyev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-17 00:00:00.000000000 Z
11
+ date: 2023-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Collects and aggregates warnings and deprecations. Optimized for production
42
56
  environment.
43
57
  email:
@@ -67,6 +81,15 @@ files:
67
81
  - lib/deprecation_collector/collectors.rb
68
82
  - lib/deprecation_collector/deprecation.rb
69
83
  - lib/deprecation_collector/version.rb
84
+ - lib/deprecation_collector/web.rb
85
+ - lib/deprecation_collector/web/application.rb
86
+ - lib/deprecation_collector/web/helpers.rb
87
+ - lib/deprecation_collector/web/router.rb
88
+ - lib/deprecation_collector/web/utils.rb
89
+ - lib/deprecation_collector/web/views/import.html.template.rb
90
+ - lib/deprecation_collector/web/views/index.html.template.rb
91
+ - lib/deprecation_collector/web/views/layout.html.template.rb
92
+ - lib/deprecation_collector/web/views/show.html.template.rb
70
93
  - sig/deprecation_collector.rbs
71
94
  homepage: https://github.com/Vasfed/deprecation_collector
72
95
  licenses:
@@ -75,7 +98,7 @@ metadata:
75
98
  homepage_uri: https://github.com/Vasfed/deprecation_collector
76
99
  source_code_uri: https://github.com/Vasfed/deprecation_collector
77
100
  changelog_uri: https://github.com/Vasfed/deprecation_collector/blob/main/CHANGELOG.md
78
- post_install_message:
101
+ post_install_message:
79
102
  rdoc_options: []
80
103
  require_paths:
81
104
  - lib
@@ -90,8 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
113
  - !ruby/object:Gem::Version
91
114
  version: '0'
92
115
  requirements: []
93
- rubygems_version: 3.4.1
94
- signing_key:
116
+ rubygems_version: 3.1.6
117
+ signing_key:
95
118
  specification_version: 4
96
119
  summary: Collector for ruby/rails deprecations and warnings, suitable for production
97
120
  test_files: []