solidstats 3.0.0.beta.1 → 3.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -0
  3. data/app/assets/javascripts/solidstats/application.js +257 -0
  4. data/app/assets/javascripts/solidstats/dashboard.js +179 -0
  5. data/app/assets/stylesheets/solidstats/application.css +6 -1
  6. data/app/controllers/solidstats/dashboard_controller.rb +28 -35
  7. data/app/controllers/solidstats/gem_metadata_controller.rb +12 -0
  8. data/app/controllers/solidstats/logs_controller.rb +12 -12
  9. data/app/controllers/solidstats/performance_controller.rb +2 -2
  10. data/app/controllers/solidstats/productivity_controller.rb +10 -10
  11. data/app/controllers/solidstats/quality_controller.rb +32 -32
  12. data/app/controllers/solidstats/securities_controller.rb +7 -7
  13. data/app/helpers/solidstats/application_helper.rb +10 -10
  14. data/app/helpers/solidstats/performance_helper.rb +32 -32
  15. data/app/helpers/solidstats/productivity_helper.rb +20 -20
  16. data/app/services/solidstats/bundler_audit_service.rb +13 -13
  17. data/app/services/solidstats/coverage_compass_service.rb +59 -59
  18. data/app/services/solidstats/load_lens_service.rb +90 -70
  19. data/app/services/solidstats/log_size_monitor_service.rb +59 -59
  20. data/app/services/solidstats/my_todo_service.rb +68 -68
  21. data/app/services/solidstats/style_patrol_service.rb +44 -44
  22. data/app/views/layouts/solidstats/application.html.erb +1 -1
  23. data/app/views/solidstats/shared/_quick_actions.html.erb +1 -1
  24. data/config/routes.rb +4 -4
  25. data/lib/generators/solidstats/clean/clean_generator.rb +24 -0
  26. data/lib/generators/solidstats/clean/templates/README +8 -0
  27. data/lib/generators/solidstats/install/install_generator.rb +32 -17
  28. data/lib/generators/solidstats/templates/initializer.rb +112 -0
  29. data/lib/solidstats/asset_compatibility.rb +238 -0
  30. data/lib/solidstats/asset_manifest.rb +205 -0
  31. data/lib/solidstats/engine.rb +49 -9
  32. data/lib/solidstats/version.rb +1 -1
  33. data/lib/solidstats.rb +24 -11
  34. data/lib/tasks/solidstats.rake +67 -0
  35. data/lib/tasks/solidstats_performance.rake +6 -29
  36. data/lib/tasks/solidstats_tasks.rake +16 -0
  37. metadata +14 -5
  38. data/lib/tasks/solidstats_install.rake +0 -13
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'find'
4
- require 'json'
3
+ require "find"
4
+ require "json"
5
5
 
6
6
  module Solidstats
7
7
  # Enhanced TODO service for comprehensive project scanning
8
8
  class MyTodoService
9
- CACHE_FILE = Rails.root.join('solidstats', 'todos.json')
9
+ CACHE_FILE = Rails.root.join("solidstats", "todos.json")
10
10
  CACHE_DURATION = 24.hours
11
-
11
+
12
12
  TODO_PATTERNS = [
13
13
  /TODO:?\s*(.+)/i,
14
14
  /FIXME:?\s*(.+)/i,
@@ -16,19 +16,19 @@ module Solidstats
16
16
  /NOTE:?\s*(.+)/i,
17
17
  /BUG:?\s*(.+)/i
18
18
  ].freeze
19
-
19
+
20
20
  SCAN_EXTENSIONS = %w[.rb .js .html .erb .yml .yaml .json .css .scss .vue .jsx .tsx .ts].freeze
21
21
  EXCLUDE_DIRS = %w[node_modules vendor tmp log public/assets .git coverage pkg app/assets/builds solidstats].freeze
22
-
22
+
23
23
  def self.collect_todos(force_refresh: false)
24
24
  return cached_todos unless force_refresh || cache_expired?
25
-
25
+
26
26
  todos = scan_project_files
27
27
  cache_todos(todos)
28
28
  update_summary_json(todos)
29
29
  todos
30
30
  end
31
-
31
+
32
32
  def self.get_summary
33
33
  todos = collect_todos
34
34
  {
@@ -44,31 +44,31 @@ module Solidstats
44
44
  last_updated: Time.current.iso8601
45
45
  }
46
46
  end
47
-
47
+
48
48
  private
49
-
49
+
50
50
  def self.scan_project_files
51
51
  todos = []
52
52
  exclude_patterns = load_gitignore_patterns
53
-
53
+
54
54
  Find.find(Rails.root) do |path|
55
55
  if File.directory?(path)
56
56
  Find.prune if should_exclude_directory?(path, exclude_patterns)
57
57
  next
58
58
  end
59
-
59
+
60
60
  next unless should_scan_file?(path)
61
61
  next if excluded_by_gitignore?(path, exclude_patterns)
62
-
62
+
63
63
  scan_file_for_todos(path, todos)
64
64
  end
65
-
66
- todos.sort_by { |todo| [todo[:file], todo[:line_number]] }
65
+
66
+ todos.sort_by { |todo| [ todo[:file], todo[:line_number] ] }
67
67
  end
68
-
68
+
69
69
  def self.scan_file_for_todos(file_path, todos)
70
- relative_path = file_path.sub("#{Rails.root}/", '')
71
-
70
+ relative_path = file_path.sub("#{Rails.root}/", "")
71
+
72
72
  File.readlines(file_path, chomp: true).each_with_index do |line, index|
73
73
  TODO_PATTERNS.each do |pattern|
74
74
  if match = line.match(pattern)
@@ -87,117 +87,117 @@ module Solidstats
87
87
  rescue => e
88
88
  Rails.logger.warn "Error scanning file #{file_path}: #{e.message}"
89
89
  end
90
-
90
+
91
91
  def self.extract_todo_type(line)
92
92
  case line.upcase
93
- when /TODO/ then 'todo'
94
- when /FIXME/ then 'fixme'
95
- when /HACK/ then 'hack'
96
- when /NOTE/ then 'note'
97
- when /BUG/ then 'bug'
98
- else 'todo'
93
+ when /TODO/ then "todo"
94
+ when /FIXME/ then "fixme"
95
+ when /HACK/ then "hack"
96
+ when /NOTE/ then "note"
97
+ when /BUG/ then "bug"
98
+ else "todo"
99
99
  end
100
100
  end
101
-
101
+
102
102
  def self.should_exclude_directory?(path, exclude_patterns)
103
- relative_path = path.sub("#{Rails.root}/", '')
104
-
103
+ relative_path = path.sub("#{Rails.root}/", "")
104
+
105
105
  # Check standard exclude directories
106
106
  EXCLUDE_DIRS.each do |dir|
107
107
  # Check if this directory or any parent directory matches
108
- path_parts = relative_path.split('/')
108
+ path_parts = relative_path.split("/")
109
109
  return true if path_parts.include?(dir)
110
110
  return true if relative_path == dir
111
111
  return true if relative_path.start_with?("#{dir}/")
112
112
  end
113
-
113
+
114
114
  # Check gitignore patterns
115
115
  return true if exclude_patterns.any? { |pattern| File.fnmatch(pattern, relative_path, File::FNM_PATHNAME) }
116
-
116
+
117
117
  false
118
118
  end
119
-
119
+
120
120
  def self.should_scan_file?(path)
121
121
  SCAN_EXTENSIONS.any? { |ext| path.end_with?(ext) }
122
122
  end
123
-
123
+
124
124
  def self.excluded_by_gitignore?(file_path, exclude_patterns)
125
- relative_path = file_path.sub("#{Rails.root}/", '')
125
+ relative_path = file_path.sub("#{Rails.root}/", "")
126
126
  exclude_patterns.any? { |pattern| File.fnmatch(pattern, relative_path, File::FNM_PATHNAME) }
127
127
  end
128
-
128
+
129
129
  def self.load_gitignore_patterns
130
- gitignore_path = Rails.root.join('.gitignore')
130
+ gitignore_path = Rails.root.join(".gitignore")
131
131
  return [] unless File.exist?(gitignore_path)
132
-
132
+
133
133
  patterns = []
134
134
  File.readlines(gitignore_path, chomp: true).each do |line|
135
135
  line = line.strip
136
- next if line.empty? || line.start_with?('#')
137
-
136
+ next if line.empty? || line.start_with?("#")
137
+
138
138
  # Convert gitignore patterns to fnmatch patterns
139
- pattern = line.gsub(/\*\*/, '*')
140
- pattern = pattern.chomp('/')
139
+ pattern = line.gsub(/\*\*/, "*")
140
+ pattern = pattern.chomp("/")
141
141
  patterns << pattern
142
- patterns << "#{pattern}/*" if !pattern.include?('*')
142
+ patterns << "#{pattern}/*" if !pattern.include?("*")
143
143
  end
144
-
144
+
145
145
  patterns
146
146
  end
147
-
147
+
148
148
  def self.cached_todos
149
149
  return [] unless File.exist?(CACHE_FILE)
150
-
150
+
151
151
  JSON.parse(File.read(CACHE_FILE), symbolize_names: true)
152
152
  rescue JSON::ParserError
153
153
  []
154
154
  end
155
-
155
+
156
156
  def self.cache_todos(todos)
157
157
  FileUtils.mkdir_p(File.dirname(CACHE_FILE))
158
158
  File.write(CACHE_FILE, todos.to_json)
159
159
  end
160
-
160
+
161
161
  def self.cache_expired?
162
162
  return true unless File.exist?(CACHE_FILE)
163
-
163
+
164
164
  File.mtime(CACHE_FILE) < CACHE_DURATION.ago
165
165
  end
166
-
166
+
167
167
  def self.update_summary_json(todos)
168
- summary_file_path = Rails.root.join('solidstats', 'summary.json')
169
-
168
+ summary_file_path = Rails.root.join("solidstats", "summary.json")
169
+
170
170
  # Ensure directory exists
171
171
  FileUtils.mkdir_p(File.dirname(summary_file_path))
172
-
172
+
173
173
  # Read existing summary or create new one
174
174
  begin
175
175
  existing_summary = File.exist?(summary_file_path) ? JSON.parse(File.read(summary_file_path)) : {}
176
176
  rescue JSON::ParserError
177
177
  existing_summary = {}
178
178
  end
179
-
179
+
180
180
  # Calculate TODO statistics
181
181
  todo_count = todos.length
182
182
  status = determine_status(todos)
183
183
  type_counts = todos.group_by { |t| t[:type] }.transform_values(&:count)
184
-
184
+
185
185
  # Create badges based on TODO types and counts
186
186
  badges = []
187
187
  badges << { "text" => "#{todo_count} Items", "color" => "info" }
188
-
188
+
189
189
  %w[todo fixme hack note bug].each do |type|
190
190
  count = type_counts[type] || 0
191
191
  if count > 0
192
192
  color = case type
193
- when 'fixme' then 'warning'
194
- when 'hack', 'bug' then 'error'
195
- else 'info'
196
- end
193
+ when "fixme" then "warning"
194
+ when "hack", "bug" then "error"
195
+ else "info"
196
+ end
197
197
  badges << { "text" => "#{type.upcase}: #{count}", "color" => color }
198
198
  end
199
199
  end
200
-
200
+
201
201
  # Update the TODO items entry
202
202
  existing_summary["TODO Items"] = {
203
203
  "icon" => "list-todo",
@@ -207,21 +207,21 @@ module Solidstats
207
207
  "url" => "/solidstats/productivity/my_todos",
208
208
  "badges" => badges
209
209
  }
210
-
210
+
211
211
  # Write updated summary
212
212
  File.write(summary_file_path, JSON.pretty_generate(existing_summary))
213
213
  Rails.logger.info("Updated summary.json with TODO items")
214
214
  rescue => e
215
215
  Rails.logger.error("Failed to update summary.json: #{e.message}")
216
216
  end
217
-
217
+
218
218
  def self.determine_status(todos)
219
219
  return "success" if todos.empty?
220
-
221
- fixme_count = todos.count { |t| t[:type] == 'fixme' }
222
- hack_count = todos.count { |t| t[:type] == 'hack' }
223
- bug_count = todos.count { |t| t[:type] == 'bug' }
224
-
220
+
221
+ fixme_count = todos.count { |t| t[:type] == "fixme" }
222
+ hack_count = todos.count { |t| t[:type] == "hack" }
223
+ bug_count = todos.count { |t| t[:type] == "bug" }
224
+
225
225
  if bug_count > 0 || hack_count > 0
226
226
  "error"
227
227
  elsif fixme_count > 0 || todos.length > 20
@@ -230,7 +230,7 @@ module Solidstats
230
230
  "success"
231
231
  end
232
232
  end
233
-
233
+
234
234
  def self.generate_message(count)
235
235
  case count
236
236
  when 0 then "No items found"
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'fileutils'
4
- require 'json'
3
+ require "fileutils"
4
+ require "json"
5
5
 
6
6
  module Solidstats
7
7
  class StylePatrolService
8
8
  CACHE_KEY = "style_patrol_data"
9
9
  CACHE_DURATION = 6.hours
10
- STANDARD_JSON_FILE = Rails.root.join('solidstats', 'standard.json')
10
+ STANDARD_JSON_FILE = Rails.root.join("solidstats", "standard.json")
11
11
 
12
12
  def self.collect_data(force_refresh: false)
13
13
  return cached_data unless force_refresh || cache_expired?
14
-
14
+
15
15
  analysis_data = analyze_code_quality
16
16
  cache_data(analysis_data)
17
17
  save_to_standard_json(analysis_data)
@@ -40,10 +40,10 @@ module Solidstats
40
40
 
41
41
  def self.analyze_code_quality
42
42
  result = `standardrb --format json 2>&1`
43
-
43
+
44
44
  # Extract JSON from output (may contain debug info or other text)
45
45
  json_content = extract_json_from_output(result)
46
-
46
+
47
47
  if json_content.nil?
48
48
  # No JSON found - could be clean result or error
49
49
  if $?.success?
@@ -51,9 +51,9 @@ module Solidstats
51
51
  {
52
52
  status: "clean",
53
53
  issues: [],
54
- summary: {
55
- total_files: 0,
56
- total_offenses: 0,
54
+ summary: {
55
+ total_files: 0,
56
+ total_offenses: 0,
57
57
  correctable_count: 0,
58
58
  target_file_count: 0,
59
59
  inspected_file_count: 0
@@ -90,10 +90,10 @@ module Solidstats
90
90
 
91
91
  def self.process_standard_output(json_data)
92
92
  issues = []
93
-
93
+
94
94
  # Handle StandardRB JSON format
95
95
  files = json_data["files"] || []
96
-
96
+
97
97
  files.each do |file_data|
98
98
  file_data["offenses"]&.each do |offense|
99
99
  issues << {
@@ -110,7 +110,7 @@ module Solidstats
110
110
 
111
111
  # Get summary from StandardRB output
112
112
  summary_data = json_data["summary"] || {}
113
-
113
+
114
114
  {
115
115
  status: issues.any? ? "issues_found" : "clean",
116
116
  issues: issues,
@@ -140,7 +140,7 @@ module Solidstats
140
140
  def self.cache_expired?
141
141
  cached_entry = Rails.cache.read(CACHE_KEY)
142
142
  return true if cached_entry.nil?
143
-
143
+
144
144
  cached_time = Time.parse(cached_entry[:analyzed_at])
145
145
  Time.current > cached_time + CACHE_DURATION
146
146
  rescue
@@ -150,46 +150,46 @@ module Solidstats
150
150
  def self.calculate_health_score(data)
151
151
  return 100 if data[:status] == "clean"
152
152
  return 0 if data[:status] == "error"
153
-
153
+
154
154
  total_offenses = data.dig(:summary, :total_offenses) || 0
155
155
  total_files = data.dig(:summary, :total_files) || 1
156
-
156
+
157
157
  # Health score: 100 - (offenses per file * 10), minimum 0
158
158
  score = 100 - ((total_offenses.to_f / total_files) * 10).round
159
- [score, 0].max
159
+ [ score, 0 ].max
160
160
  end
161
161
 
162
162
  def self.update_summary_json(data)
163
- summary_file_path = Rails.root.join('solidstats', 'summary.json')
164
-
163
+ summary_file_path = Rails.root.join("solidstats", "summary.json")
164
+
165
165
  # Ensure directory exists
166
166
  FileUtils.mkdir_p(File.dirname(summary_file_path))
167
-
167
+
168
168
  # Read existing summary or create new one
169
169
  begin
170
170
  existing_summary = File.exist?(summary_file_path) ? JSON.parse(File.read(summary_file_path)) : {}
171
171
  rescue JSON::ParserError
172
172
  existing_summary = {}
173
173
  end
174
-
174
+
175
175
  # Calculate style patrol statistics
176
176
  total_offenses = data.dig(:summary, :total_offenses) || 0
177
177
  correctable_count = data.dig(:summary, :correctable_count) || 0
178
178
  status = determine_dashboard_status(data[:status], total_offenses)
179
179
  health_score = calculate_health_score(data)
180
-
180
+
181
181
  # Create badges based on code quality metrics
182
182
  badges = []
183
183
  badges << { "text" => "Health: #{health_score}%", "color" => health_badge_color(health_score) }
184
-
184
+
185
185
  if total_offenses > 0
186
186
  badges << { "text" => "#{total_offenses} Issues", "color" => "warning" }
187
-
187
+
188
188
  if correctable_count > 0
189
189
  badges << { "text" => "#{correctable_count} Auto-fixable", "color" => "info" }
190
190
  end
191
191
  end
192
-
192
+
193
193
  # Update the StylePatrol entry
194
194
  existing_summary["StylePatrol"] = {
195
195
  "icon" => "code",
@@ -199,7 +199,7 @@ module Solidstats
199
199
  "url" => "/solidstats/quality/style_patrol",
200
200
  "badges" => badges
201
201
  }
202
-
202
+
203
203
  # Write updated summary
204
204
  File.write(summary_file_path, JSON.pretty_generate(existing_summary))
205
205
  Rails.logger.info("Updated summary.json with StylePatrol data")
@@ -246,7 +246,7 @@ module Solidstats
246
246
  def self.save_to_standard_json(data)
247
247
  # Ensure directory exists
248
248
  FileUtils.mkdir_p(File.dirname(STANDARD_JSON_FILE))
249
-
249
+
250
250
  # Prepare data for standard.json file
251
251
  standard_data = {
252
252
  last_updated: data[:analyzed_at],
@@ -257,7 +257,7 @@ module Solidstats
257
257
  processed_summary: data[:summary] || {},
258
258
  issues_count: data[:issues]&.count || 0
259
259
  }
260
-
260
+
261
261
  # Write to standard.json file
262
262
  File.write(STANDARD_JSON_FILE, JSON.pretty_generate(standard_data))
263
263
  Rails.logger.info("Saved StandardRB data to #{STANDARD_JSON_FILE}")
@@ -268,47 +268,47 @@ module Solidstats
268
268
  def self.extract_json_from_output(output)
269
269
  # Look for JSON content - should start with { and end with }
270
270
  # Handle cases where debug info or other text appears before/after JSON
271
-
271
+
272
272
  return nil if output.nil? || output.strip.empty?
273
-
273
+
274
274
  # Split by lines and look for the line that starts with JSON
275
275
  lines = output.split("\n")
276
276
  json_lines = []
277
277
  json_started = false
278
278
  brace_count = 0
279
-
279
+
280
280
  lines.each do |line|
281
281
  # Skip debug lines that mention "Subprocess Debugger", "ruby-debug-ide", etc.
282
- next if line.include?("Subprocess Debugger") ||
283
- line.include?("ruby-debug-ide") ||
282
+ next if line.include?("Subprocess Debugger") ||
283
+ line.include?("ruby-debug-ide") ||
284
284
  line.include?("debase") ||
285
285
  line.include?("listens on")
286
-
286
+
287
287
  # Look for the start of JSON (line starting with {)
288
- if !json_started && line.strip.start_with?('{')
288
+ if !json_started && line.strip.start_with?("{")
289
289
  json_started = true
290
290
  end
291
-
291
+
292
292
  if json_started
293
293
  json_lines << line
294
-
294
+
295
295
  # Count braces to know when JSON ends
296
- brace_count += line.count('{') - line.count('}')
297
-
296
+ brace_count += line.count("{") - line.count("}")
297
+
298
298
  # If we've closed all braces, we've reached the end of JSON
299
299
  break if brace_count == 0
300
300
  end
301
301
  end
302
-
302
+
303
303
  return nil if json_lines.empty?
304
-
304
+
305
305
  json_content = json_lines.join("\n")
306
-
306
+
307
307
  # Validate that it looks like StandardRB JSON by checking for expected structure
308
- return nil unless json_content.include?('"metadata"') ||
309
- json_content.include?('"files"') ||
308
+ return nil unless json_content.include?('"metadata"') ||
309
+ json_content.include?('"files"') ||
310
310
  json_content.include?('"summary"')
311
-
311
+
312
312
  json_content
313
313
  rescue => e
314
314
  Rails.logger.error("Error extracting JSON from StandardRB output: #{e.message}")
@@ -4,7 +4,7 @@
4
4
  <title>Solidstats</title>
5
5
  <%= csrf_meta_tags %>
6
6
  <%= csp_meta_tag %>
7
-
7
+
8
8
  <!-- Solidstats CDN Dependencies -->
9
9
  <%= solidstats_cdn_dependencies %>
10
10
 
@@ -10,7 +10,7 @@
10
10
  <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
11
11
  <% quick_actions.each do |action| %>
12
12
  <button class="btn btn-outline btn-sm group flex flex-col items-center p-4 h-auto min-h-16
13
- hover:btn-<%= action[:color] %> transition-all duration-200" disabled>
13
+ hover:btn-<%= action[:color] %> transition-all duration-200">
14
14
  <div class="w-10 h-10 bg-gradient-to-r from-<%= action[:color] %>-500 to-<%= action[:color] %>-600
15
15
  rounded-lg flex items-center justify-center mb-2
16
16
  group-hover:scale-110 transition-transform duration-200 shadow-lg">
data/config/routes.rb CHANGED
@@ -7,17 +7,17 @@ Solidstats::Engine.routes.draw do
7
7
  get "logs/size", to: "logs#logs_size", as: :logs_size
8
8
  post "logs/truncate/:filename", to: "logs#truncate", as: :truncate_log, constraints: { filename: /.+/ }
9
9
  post "logs/refresh", to: "logs#refresh", as: :refresh_logs
10
-
10
+
11
11
  # Security-related routes
12
12
  get "securities/bundler_audit", to: "securities#bundler_audit", as: :securities_bundler_audit
13
13
  post "securities/refresh_bundler_audit", to: "securities#refresh_bundler_audit", as: :refresh_securities_bundler_audit
14
-
14
+
15
15
  # Quality-related routes
16
16
  get "quality/style_patrol", to: "quality#style_patrol", as: :quality_style_patrol
17
17
  post "quality/refresh_style_patrol", to: "quality#refresh_style_patrol", as: :refresh_quality_style_patrol
18
18
  get "quality/coverage_compass", to: "quality#coverage_compass", as: :quality_coverage_compass
19
19
  post "quality/refresh_coverage_compass", to: "quality#refresh_coverage_compass", as: :refresh_quality_coverage_compass
20
-
20
+
21
21
  # Productivity-related routes
22
22
  resources :productivity, only: [] do
23
23
  collection do
@@ -25,7 +25,7 @@ Solidstats::Engine.routes.draw do
25
25
  post :refresh_todos
26
26
  end
27
27
  end
28
-
28
+
29
29
  # Performance-related routes
30
30
  resources :performance, only: [] do
31
31
  collection do
@@ -0,0 +1,24 @@
1
+ require "rails/generators/base"
2
+
3
+ module Solidstats
4
+ module Generators
5
+ # This generator cleans up Solidstats data by invoking the Rake task
6
+ #
7
+ # @example
8
+ # $ rails generate solidstats:clean
9
+ # or
10
+ # $ rake solidstats:clean
11
+ class CleanGenerator < Rails::Generators::Base
12
+ source_root File.expand_path("templates", __dir__)
13
+ desc "Cleans up Solidstats data in your Rails application"
14
+
15
+ def run_clean_task
16
+ rake "solidstats:clean"
17
+ end
18
+
19
+ def show_readme
20
+ readme "README" if behavior == :invoke
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ The Solidstats cleanup task has been executed.
2
+
3
+ All generated data, including JSON files and caches in the 'solidstats' directory, have been removed.
4
+
5
+ You can run this task again at any time by executing:
6
+ `rails generate solidstats:clean`
7
+ or
8
+ `rake solidstats:clean`
@@ -2,7 +2,7 @@ require "rails/generators/base"
2
2
 
3
3
  module Solidstats
4
4
  module Generators
5
- # This generator installs Solidstats routes in the host application
5
+ # This generator installs Solidstats in the host application
6
6
  #
7
7
  # @example
8
8
  # $ rails generate solidstats:install
@@ -17,13 +17,19 @@ module Solidstats
17
17
  desc "Installs Solidstats in your Rails application"
18
18
 
19
19
  def add_routes
20
- route_code = <<-RUBY
20
+ route_string = %Q(mount Solidstats::Engine => "/solidstats")
21
+ route_code = %Q(
21
22
  # Solidstats Routes (development only)
22
- mount Solidstats::Engine => "/solidstats" if Rails.env.development?
23
- RUBY
23
+ #{route_string} if Rails.env.development?
24
+ )
24
25
 
25
- route route_code
26
- say_status :routes, "Mounting Solidstats engine at /solidstats (development environment only)", :green
26
+ # Check if the route already exists
27
+ if File.read(File.join(destination_root, "config", "routes.rb")).include?(route_string)
28
+ say_status :skip, "Solidstats route already exists", :yellow
29
+ else
30
+ route route_code.strip
31
+ say_status :routes, "Mounting Solidstats engine at /solidstats (development only)", :green
32
+ end
27
33
  end
28
34
 
29
35
  def create_solidstats_directory
@@ -35,23 +41,32 @@ module Solidstats
35
41
  def add_to_gitignore
36
42
  gitignore_path = File.join(destination_root, ".gitignore")
37
43
  gitignore_content = "\n# Solidstats data directory\nsolidstats/\n"
38
-
44
+
39
45
  if File.exist?(gitignore_path)
40
- existing_content = File.read(gitignore_path)
41
- unless existing_content.include?("solidstats/")
42
- append_to_file ".gitignore", gitignore_content
43
- say_status :update, ".gitignore to exclude solidstats directory", :green
44
- else
45
- say_status :skip, ".gitignore already contains solidstats exclusion", :yellow
46
- end
46
+ append_to_file ".gitignore", gitignore_content unless File.read(gitignore_path).include?("solidstats/")
47
47
  else
48
48
  create_file ".gitignore", gitignore_content.strip
49
- say_status :create, ".gitignore with solidstats exclusion", :green
50
49
  end
50
+ say_status :update, ".gitignore to exclude solidstats directory", :green
51
51
  end
52
52
 
53
- def show_readme
54
- readme "README" if behavior == :invoke
53
+ def show_next_steps
54
+ say ""
55
+ say "✅ Solidstats has been installed successfully!", :green
56
+ say ""
57
+ say "To get started, you need to prime the data for the dashboard."
58
+ say "You can prime data for all services at once by running:", :yellow
59
+ say " rake solidstats:prime:all", :cyan
60
+ say ""
61
+ say "Or, you can run them individually:", :yellow
62
+ say " rake solidstats:prime:log_size"
63
+ say " rake solidstats:prime:bundler_audit"
64
+ say " rake solidstats:prime:todos"
65
+ say " rake solidstats:prime:style_patrol"
66
+ say " rake solidstats:prime:coverage"
67
+ say " rake solidstats:prime:load_lens"
68
+ say ""
69
+ say "After the tasks complete, start your server and visit http://localhost:3000/solidstats to see the dashboard."
55
70
  end
56
71
  end
57
72
  end