railsforge 1.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 (73) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +528 -0
  4. data/bin/railsforge +8 -0
  5. data/lib/railsforge/analyzers/base_analyzer.rb +41 -0
  6. data/lib/railsforge/analyzers/controller_analyzer.rb +83 -0
  7. data/lib/railsforge/analyzers/database_analyzer.rb +55 -0
  8. data/lib/railsforge/analyzers/metrics_analyzer.rb +55 -0
  9. data/lib/railsforge/analyzers/model_analyzer.rb +74 -0
  10. data/lib/railsforge/analyzers/performance_analyzer.rb +161 -0
  11. data/lib/railsforge/analyzers/refactor_analyzer.rb +118 -0
  12. data/lib/railsforge/analyzers/security_analyzer.rb +169 -0
  13. data/lib/railsforge/analyzers/spec_analyzer.rb +58 -0
  14. data/lib/railsforge/api_generator.rb +397 -0
  15. data/lib/railsforge/audit.rb +289 -0
  16. data/lib/railsforge/cli.rb +671 -0
  17. data/lib/railsforge/config.rb +181 -0
  18. data/lib/railsforge/database_analyzer.rb +300 -0
  19. data/lib/railsforge/doctor.rb +250 -0
  20. data/lib/railsforge/feature_generator.rb +560 -0
  21. data/lib/railsforge/generator.rb +313 -0
  22. data/lib/railsforge/generators/base_generator.rb +70 -0
  23. data/lib/railsforge/generators/demo_generator.rb +307 -0
  24. data/lib/railsforge/generators/devops_generator.rb +287 -0
  25. data/lib/railsforge/generators/monitoring_generator.rb +134 -0
  26. data/lib/railsforge/generators/service_generator.rb +122 -0
  27. data/lib/railsforge/generators/stimulus_controller_generator.rb +129 -0
  28. data/lib/railsforge/generators/test_generator.rb +289 -0
  29. data/lib/railsforge/generators/view_component_generator.rb +169 -0
  30. data/lib/railsforge/graph.rb +270 -0
  31. data/lib/railsforge/loader.rb +56 -0
  32. data/lib/railsforge/mailer_generator.rb +191 -0
  33. data/lib/railsforge/plugins/plugin_loader.rb +60 -0
  34. data/lib/railsforge/plugins.rb +30 -0
  35. data/lib/railsforge/profiles/admin_app.yml +49 -0
  36. data/lib/railsforge/profiles/api_only.yml +47 -0
  37. data/lib/railsforge/profiles/blog.yml +47 -0
  38. data/lib/railsforge/profiles/standard.yml +44 -0
  39. data/lib/railsforge/profiles.rb +99 -0
  40. data/lib/railsforge/refactor_analyzer.rb +401 -0
  41. data/lib/railsforge/refactor_controller.rb +277 -0
  42. data/lib/railsforge/refactors/refactor_controller.rb +117 -0
  43. data/lib/railsforge/template_loader.rb +105 -0
  44. data/lib/railsforge/templates/v1/form/spec_template.rb +18 -0
  45. data/lib/railsforge/templates/v1/form/template.rb +28 -0
  46. data/lib/railsforge/templates/v1/job/spec_template.rb +17 -0
  47. data/lib/railsforge/templates/v1/job/template.rb +13 -0
  48. data/lib/railsforge/templates/v1/policy/spec_template.rb +41 -0
  49. data/lib/railsforge/templates/v1/policy/template.rb +57 -0
  50. data/lib/railsforge/templates/v1/presenter/spec_template.rb +12 -0
  51. data/lib/railsforge/templates/v1/presenter/template.rb +13 -0
  52. data/lib/railsforge/templates/v1/query/spec_template.rb +12 -0
  53. data/lib/railsforge/templates/v1/query/template.rb +16 -0
  54. data/lib/railsforge/templates/v1/serializer/spec_template.rb +13 -0
  55. data/lib/railsforge/templates/v1/serializer/template.rb +11 -0
  56. data/lib/railsforge/templates/v1/service/spec_template.rb +12 -0
  57. data/lib/railsforge/templates/v1/service/template.rb +25 -0
  58. data/lib/railsforge/templates/v1/stimulus_controller/template.rb +35 -0
  59. data/lib/railsforge/templates/v1/view_component/template.rb +24 -0
  60. data/lib/railsforge/templates/v2/job/template.rb +49 -0
  61. data/lib/railsforge/templates/v2/query/template.rb +66 -0
  62. data/lib/railsforge/templates/v2/service/spec_template.rb +33 -0
  63. data/lib/railsforge/templates/v2/service/template.rb +71 -0
  64. data/lib/railsforge/templates/v3/job/template.rb +72 -0
  65. data/lib/railsforge/templates/v3/query/spec_template.rb +54 -0
  66. data/lib/railsforge/templates/v3/query/template.rb +115 -0
  67. data/lib/railsforge/templates/v3/service/spec_template.rb +51 -0
  68. data/lib/railsforge/templates/v3/service/template.rb +84 -0
  69. data/lib/railsforge/version.rb +5 -0
  70. data/lib/railsforge/wizard.rb +265 -0
  71. data/lib/railsforge/wizard_tui.rb +286 -0
  72. data/lib/railsforge.rb +13 -0
  73. metadata +216 -0
@@ -0,0 +1,671 @@
1
+ # CLI module for RailsForge
2
+ # Handles all CLI commands
3
+
4
+ module RailsForge
5
+ # CLI class handles command-line interface
6
+ class CLI
7
+ # Main entry point
8
+ def self.start(args)
9
+ command = args.shift
10
+
11
+ case command
12
+ when "new"
13
+ handle_new_command(args)
14
+ when "generate", "g"
15
+ handle_generate_command(args)
16
+ when "analyze", "a"
17
+ handle_analyze_command(args)
18
+ when "refactor", "r"
19
+ handle_refactor_command(args)
20
+ when "doctor"
21
+ handle_doctor_command(args)
22
+ when "audit"
23
+ handle_audit_command(args)
24
+ when "graph"
25
+ handle_graph_command(args)
26
+ when "wizard", "wiz"
27
+ handle_wizard_command(args)
28
+ when "plugins", "plug"
29
+ handle_plugins_command(args)
30
+ when "config", "cfg"
31
+ handle_config_command(args)
32
+ when "profiles"
33
+ puts RailsForge::Profile.show_available
34
+ when "--version", "-v"
35
+ puts "RailsForge #{VERSION}"
36
+ when nil, "--help", "-h"
37
+ display_help
38
+ else
39
+ puts "Unknown command: #{command}"
40
+ display_help
41
+ exit 1
42
+ end
43
+ end
44
+
45
+ # Display help
46
+ def self.display_help
47
+ puts <<~HELP
48
+ RailsForge - A Rails development toolkit
49
+
50
+ Usage:
51
+ railsforge new <app_name> Create a new Rails app
52
+ railsforge generate service <name> Generate a service object
53
+ railsforge generate query <name> Generate a query object
54
+ railsforge generate job <name> Generate a job object
55
+ railsforge generate demo <name> Generate a demo project
56
+ railsforge generate devops Generate Docker/CI-CD configs
57
+ railsforge generate monitoring Generate Sentry/Lograge configs
58
+ railsforge generate test <name> Generate test files
59
+ railsforge analyze Analyze code quality
60
+ railsforge doctor Full project health check
61
+ railsforge audit Architecture audit
62
+ railsforge graph Dependency graph
63
+ railsforge refactor Refactoring suggestions
64
+ railsforge wizard Interactive project setup
65
+ railsforge plugins Plugin management
66
+ railsforge config Configuration
67
+ railsforge profiles List available profiles
68
+ railsforge --version, -v Show version
69
+ railsforge --help, -h Show this help
70
+ HELP
71
+ end
72
+
73
+ # Handle new command
74
+ def self.handle_new_command(args)
75
+ options = {}
76
+ app_name = nil
77
+ interactive = true
78
+
79
+ args.each do |arg|
80
+ if arg.start_with?("--")
81
+ key, value = arg[2..].split("=", 2)
82
+ interactive = false
83
+ case key
84
+ when "auth"
85
+ options[:auth] = value || "devise"
86
+ when "admin"
87
+ options[:admin] = value || "activeadmin"
88
+ when "jobs"
89
+ options[:jobs] = value || "sidekiq"
90
+ when "profile"
91
+ options[:profile] = value
92
+ end
93
+ elsif !arg.start_with?("-") && app_name.nil?
94
+ app_name = arg
95
+ end
96
+ end
97
+
98
+ if app_name.nil?
99
+ puts "Usage: railsforge new <app_name> [options]"
100
+ exit 1
101
+ end
102
+
103
+ if interactive
104
+ options = prompt_for_features(app_name)
105
+ end
106
+
107
+ begin
108
+ result = RailsForge::Generator.create_app(app_name, options)
109
+ puts "\n#{result}"
110
+ rescue => e
111
+ puts "Error: #{e.message}"
112
+ exit 1
113
+ end
114
+ end
115
+
116
+ # Prompt for features
117
+ def self.prompt_for_features(app_name)
118
+ options = {}
119
+ puts "\n#{'=' * 50}"
120
+ puts "RailsForge Interactive Setup"
121
+ puts "#{'=' * 50}"
122
+
123
+ if prompt_yes_no("Add authentication?")
124
+ options[:auth] = "devise"
125
+ end
126
+
127
+ if prompt_yes_no("Add admin panel?")
128
+ options[:admin] = "activeadmin"
129
+ end
130
+
131
+ if prompt_yes_no("Add background jobs?")
132
+ options[:jobs] = "sidekiq"
133
+ end
134
+
135
+ options
136
+ end
137
+
138
+ # Prompt yes/no
139
+ def self.prompt_yes_no(question, default: false)
140
+ suffix = default ? " [Y/n]" : " [y/N]"
141
+ print "#{question}#{suffix}: "
142
+ answer = STDIN.gets.strip.downcase
143
+ return default if answer.empty?
144
+ answer == "y" || answer == "yes"
145
+ end
146
+
147
+ # Handle generate command
148
+ def self.handle_generate_command(args)
149
+ template_version = "v1"
150
+ dry_run = false
151
+
152
+ # Parse options
153
+ args = args.reject do |arg|
154
+ if arg.start_with?("--template=")
155
+ template_version = arg.split("=").last
156
+ true
157
+ elsif arg == "--dry-run"
158
+ dry_run = true
159
+ true
160
+ else
161
+ false
162
+ end
163
+ end
164
+
165
+ generator_type = args.shift
166
+ names = args # Multiple names allowed for bulk generation
167
+
168
+ # Generators that don't require names
169
+ no_name_generators = ["devops", "ops", "monitoring", "mon"]
170
+
171
+ # Handle bulk generation
172
+ if names.empty? && generator_type && !no_name_generators.include?(generator_type)
173
+ puts "Error: Name required"
174
+ exit 1
175
+ end
176
+
177
+ case generator_type
178
+ when "service", "s"
179
+ handle_generate_bulk(:service, names, template_version, dry_run)
180
+ when "query", "q"
181
+ handle_generate_bulk(:query, names, template_version, dry_run)
182
+ when "job", "j"
183
+ handle_generate_bulk(:job, names, template_version, dry_run)
184
+ when "form", "f"
185
+ handle_generate_bulk(:form, names, template_version, dry_run)
186
+ when "presenter", "p"
187
+ handle_generate_bulk(:presenter, names, template_version, dry_run)
188
+ when "policy", "pol"
189
+ handle_generate_bulk(:policy, names, template_version, dry_run)
190
+ when "serializer", "ser"
191
+ handle_generate_bulk(:serializer, names, template_version, dry_run)
192
+ when "component", "c"
193
+ handle_generate_bulk(:component, names, template_version, dry_run)
194
+ when "stimulus", "stim"
195
+ handle_generate_bulk(:stimulus, names, template_version, dry_run)
196
+ when "demo"
197
+ handle_generate_demo(args, names.first)
198
+ when "devops", "ops"
199
+ handle_generate_devops(args)
200
+ when "monitoring", "mon"
201
+ handle_generate_monitoring(args)
202
+ when "test", "t"
203
+ handle_generate_test(args, names.first)
204
+ when "mailer", "mail"
205
+ handle_generate_bulk(:mailer, names, template_version, dry_run)
206
+ when "feature", "feat"
207
+ handle_generate_feature(args, names.first)
208
+ when "api"
209
+ handle_generate_api(args, names.first)
210
+ else
211
+ puts "Usage: railsforge generate <type> <name> [<name>...]"
212
+ puts "Types: service, query, job, form, presenter, policy, serializer, component, stimulus, mailer, feature, api"
213
+ puts "Options: --template=v2, --dry-run"
214
+ exit 1
215
+ end
216
+ end
217
+
218
+ # Handle bulk generation
219
+ def self.handle_generate_bulk(type, names, template_version, dry_run)
220
+ if dry_run
221
+ puts "Dry run - would generate:"
222
+ names.each { |name| puts " - #{type}: #{name} (template: #{template_version})" }
223
+ return
224
+ end
225
+
226
+ results = []
227
+ names.each do |name|
228
+ result = generate_single(type, name, template_version)
229
+ results << result
230
+ end
231
+
232
+ puts results.join("\n")
233
+ end
234
+
235
+ # Generate a single item
236
+ def self.generate_single(type, name, template_version)
237
+ case type
238
+ when :service
239
+ "Generating service: #{name}" + "\n" + RailsForge::Generators::ServiceGenerator.generate(name, with_spec: true, template_version: template_version)
240
+ when :query
241
+ "Generating query: #{name}"
242
+ when :job
243
+ "Generating job: #{name}"
244
+ when :component
245
+ "Generating component: #{name}" + "\n" + RailsForge::Generators::ViewComponentGenerator.new(name, template_version: template_version).generate
246
+ when :stimulus
247
+ "Generating stimulus: #{name}" + "\n" + RailsForge::Generators::StimulusControllerGenerator.new(name, template_version: template_version).generate
248
+ else
249
+ "Generator for #{type} not fully implemented"
250
+ end
251
+ rescue => e
252
+ "Error generating #{name}: #{e.message}"
253
+ end
254
+
255
+ # Generate service
256
+ def self.handle_generate_service(args, name, template_version)
257
+ with_spec = !args.include?("--no-spec")
258
+
259
+ begin
260
+ puts "Generating service: #{name}..."
261
+ result = RailsForge::Generators::ServiceGenerator.generate(name, with_spec: with_spec, template_version: template_version)
262
+ puts "\n#{result}"
263
+ rescue => e
264
+ puts "Error: #{e.message}"
265
+ exit 1
266
+ end
267
+ end
268
+
269
+ # Generate query
270
+ def self.handle_generate_query(args, name, template_version)
271
+ with_spec = !args.include?("--no-spec")
272
+
273
+ begin
274
+ puts "Generating query: #{name}..."
275
+ result = RailsForge::Generators::QueryGenerator.generate(name, with_spec: with_spec, template_version: template_version)
276
+ puts "\n#{result}"
277
+ rescue => e
278
+ puts "Error: #{e.message}"
279
+ exit 1
280
+ end
281
+ end
282
+
283
+ # Generate job
284
+ def self.handle_generate_job(args, name, template_version)
285
+ with_spec = !args.include?("--no-spec")
286
+
287
+ begin
288
+ puts "Generating job: #{name}..."
289
+ result = RailsForge::Generators::JobGenerator.generate(name, with_spec: with_spec, template_version: template_version)
290
+ puts "\n#{result}"
291
+ rescue => e
292
+ puts "Error: #{e.message}"
293
+ exit 1
294
+ end
295
+ end
296
+
297
+ # Generate form
298
+ def self.handle_generate_form(args, name, template_version)
299
+ with_spec = !args.include?("--no-spec")
300
+
301
+ begin
302
+ puts "Generating form: #{name}..."
303
+ result = RailsForge::Generators::FormGenerator.generate(name, with_spec: with_spec, template_version: template_version)
304
+ puts "\n#{result}"
305
+ rescue => e
306
+ puts "Error: #{e.message}"
307
+ exit 1
308
+ end
309
+ end
310
+
311
+ # Generate presenter
312
+ def self.handle_generate_presenter(args, name, template_version)
313
+ with_spec = !args.include?("--no-spec")
314
+
315
+ begin
316
+ puts "Generating presenter: #{name}..."
317
+ result = RailsForge::Generators::PresenterGenerator.generate(name, with_spec: with_spec, template_version: template_version)
318
+ puts "\n#{result}"
319
+ rescue => e
320
+ puts "Error: #{e.message}"
321
+ exit 1
322
+ end
323
+ end
324
+
325
+ # Generate policy
326
+ def self.handle_generate_policy(args, name, template_version)
327
+ with_spec = !args.include?("--no-spec")
328
+
329
+ begin
330
+ puts "Generating policy: #{name}..."
331
+ result = RailsForge::Generators::PolicyGenerator.generate(name, with_spec: with_spec, template_version: template_version)
332
+ puts "\n#{result}"
333
+ rescue => e
334
+ puts "Error: #{e.message}"
335
+ exit 1
336
+ end
337
+ end
338
+
339
+ # Generate serializer
340
+ def self.handle_generate_serializer(args, name, template_version)
341
+ with_spec = !args.include?("--no-spec")
342
+
343
+ begin
344
+ puts "Generating serializer: #{name}..."
345
+ result = RailsForge::Generators::SerializerGenerator.generate(name, with_spec: with_spec, template_version: template_version)
346
+ puts "\n#{result}"
347
+ rescue => e
348
+ puts "Error: #{e.message}"
349
+ exit 1
350
+ end
351
+ end
352
+
353
+ # Generate mailer
354
+ def self.handle_generate_mailer(args, name)
355
+ with_spec = !args.include?("--no-spec")
356
+
357
+ begin
358
+ puts "Generating mailer: #{name}..."
359
+ result = RailsForge::Generators::MailerGenerator.generate(name, with_spec: with_spec)
360
+ puts "\n#{result}"
361
+ rescue => e
362
+ puts "Error: #{e.message}"
363
+ exit 1
364
+ end
365
+ end
366
+
367
+ # Generate feature
368
+ def self.handle_generate_feature(args, name)
369
+ with_spec = !args.include?("--no-spec")
370
+
371
+ begin
372
+ puts "Generating feature: #{name}..."
373
+ result = RailsForge::Generators::FeatureGenerator.generate(name, with_spec: with_spec)
374
+ puts "\n#{result}"
375
+ rescue => e
376
+ puts "Error: #{e.message}"
377
+ exit 1
378
+ end
379
+ end
380
+
381
+ # Generate API
382
+ def self.handle_generate_api(args, name)
383
+ with_spec = !args.include?("--no-spec")
384
+
385
+ begin
386
+ puts "Generating API resource: #{name}..."
387
+ result = RailsForge::Generators::ApiGenerator.generate(name, with_spec: with_spec)
388
+ puts "\n#{result}"
389
+ rescue => e
390
+ puts "Error: #{e.message}"
391
+ exit 1
392
+ end
393
+ end
394
+
395
+ # Generate demo project
396
+ def self.handle_generate_demo(args, name)
397
+ options = {}
398
+ args.each do |arg|
399
+ if arg.start_with?("--")
400
+ key, value = arg[2..].split("=", 2)
401
+ options[key.to_sym] = value || true
402
+ end
403
+ end
404
+
405
+ begin
406
+ puts "Generating demo project: #{name}..."
407
+ result = RailsForge::Generators::DemoGenerator.new(name, options).generate
408
+ puts "\n#{result}"
409
+ rescue => e
410
+ puts "Error: #{e.message}"
411
+ exit 1
412
+ end
413
+ end
414
+
415
+ # Generate devops configs
416
+ def self.handle_generate_devops(args)
417
+ options = {}
418
+ args.each do |arg|
419
+ if arg.start_with?("--")
420
+ key, value = arg[2..].split("=", 2)
421
+ options[key.to_sym] = value || true
422
+ end
423
+ end
424
+
425
+ begin
426
+ puts "Generating DevOps configurations..."
427
+ result = RailsForge::Generators::DevopsGenerator.new("devops", options).generate
428
+ puts "\n#{result}"
429
+ rescue => e
430
+ puts "Error: #{e.message}"
431
+ exit 1
432
+ end
433
+ end
434
+
435
+ # Generate monitoring configs
436
+ def self.handle_generate_monitoring(args)
437
+ options = {}
438
+ args.each do |arg|
439
+ if arg.start_with?("--")
440
+ key, value = arg[2..].split("=", 2)
441
+ options[key.to_sym] = value || true
442
+ end
443
+ end
444
+
445
+ begin
446
+ puts "Generating Monitoring configurations..."
447
+ result = RailsForge::Generators::MonitoringGenerator.new("monitoring", options).generate
448
+ puts "\n#{result}"
449
+ rescue => e
450
+ puts "Error: #{e.message}"
451
+ exit 1
452
+ end
453
+ end
454
+
455
+ # Generate test files
456
+ def self.handle_generate_test(args, name)
457
+ options = { type: "model" }
458
+ args.each do |arg|
459
+ if arg.start_with?("--")
460
+ key, value = arg[2..].split("=", 2)
461
+ options[key.to_sym] = value || true
462
+ end
463
+ end
464
+
465
+ begin
466
+ puts "Generating test files for: #{name}..."
467
+ result = RailsForge::Generators::TestGenerator.new(name, options).generate
468
+ puts "\n#{result}"
469
+ rescue => e
470
+ puts "Error: #{e.message}"
471
+ exit 1
472
+ end
473
+ end
474
+
475
+ # Handle analyze command
476
+ def self.handle_analyze_command(args)
477
+ target = args.shift
478
+
479
+ case target
480
+ when nil, "controllers", "c"
481
+ analyze_controllers
482
+ when "models", "m"
483
+ analyze_models
484
+ when "specs", "spec", "s"
485
+ analyze_specs
486
+ when "db", "database", "d"
487
+ analyze_db
488
+ when "metrics", "metric", "met"
489
+ analyze_metrics(args)
490
+ when "security", "sec", "security"
491
+ analyze_security
492
+ when "performance", "perf", "p"
493
+ analyze_performance
494
+ when "all", "full", "a"
495
+ analyze_all
496
+ else
497
+ puts "Unknown analyze target: #{target}"
498
+ puts "Available: controllers, models, specs, db, metrics, security, performance, all"
499
+ exit 1
500
+ end
501
+ end
502
+
503
+ def self.analyze_security
504
+ results = RailsForge::Analyzers::SecurityAnalyzer.analyze
505
+ RailsForge::Analyzers::SecurityAnalyzer.print_report(results)
506
+ end
507
+
508
+ def self.analyze_performance
509
+ results = RailsForge::Analyzers::PerformanceAnalyzer.analyze
510
+ RailsForge::Analyzers::PerformanceAnalyzer.print_report(results)
511
+ end
512
+
513
+ def self.analyze_controllers
514
+ results = RailsForge::Analyzers::ControllerAnalyzer.analyze
515
+ RailsForge::Analyzers::ControllerAnalyzer.print_results(results)
516
+ end
517
+
518
+ def self.analyze_models
519
+ results = RailsForge::Analyzers::ModelAnalyzer.analyze
520
+ RailsForge::Analyzers::ModelAnalyzer.print_results(results)
521
+ end
522
+
523
+ def self.analyze_specs
524
+ results = RailsForge::Analyzers::SpecAnalyzer.analyze
525
+ RailsForge::Analyzers::SpecAnalyzer.print_results(results)
526
+ end
527
+
528
+ def self.analyze_db
529
+ results = RailsForge::Analyzers::DatabaseAnalyzer.analyze
530
+ RailsForge::Analyzers::DatabaseAnalyzer.print_report(results)
531
+ end
532
+
533
+ def self.analyze_metrics(args)
534
+ results = RailsForge::Analyzers::MetricsAnalyzer.analyze
535
+ RailsForge::Analyzers::MetricsAnalyzer.print_results(results)
536
+ end
537
+
538
+ def self.analyze_all
539
+ RailsForge::ReportFormatter.generate_report
540
+ end
541
+
542
+ # Handle refactor command
543
+ def self.handle_refactor_command(args)
544
+ target = args.shift
545
+
546
+ case target
547
+ when nil, "controllers", "c"
548
+ refactor_controllers
549
+ when "models", "m"
550
+ refactor_models
551
+ when "controller"
552
+ refactor_specific_controller(args.shift)
553
+ else
554
+ puts "Usage: railsforge refactor [controllers|models|controller <name>]"
555
+ exit 1
556
+ end
557
+ end
558
+
559
+ def self.refactor_controllers
560
+ results = RailsForge::Analyzers::RefactorAnalyzer.analyze_controllers
561
+ RailsForge::Analyzers::RefactorAnalyzer.print_report(results)
562
+ end
563
+
564
+ def self.refactor_models
565
+ results = RailsForge::Analyzers::RefactorAnalyzer.analyze_models
566
+ RailsForge::Analyzers::RefactorAnalyzer.print_report(results)
567
+ end
568
+
569
+ def self.refactor_specific_controller(name)
570
+ refactor = RailsForge::Refactors::RefactorController.new
571
+ refactor.refactor(name)
572
+ end
573
+
574
+ # Handle doctor command
575
+ def self.handle_doctor_command(args)
576
+ doctor = RailsForge::Doctor.new
577
+ doctor.run
578
+ rescue => e
579
+ puts "Error: #{e.message}"
580
+ exit 1
581
+ end
582
+
583
+ # Handle audit command
584
+ def self.handle_audit_command(args)
585
+ results = RailsForge::Audit.run
586
+ RailsForge::Audit.print_report(results)
587
+ rescue => e
588
+ puts "Error: #{e.message}"
589
+ exit 1
590
+ end
591
+
592
+ # Handle graph command
593
+ def self.handle_graph_command(args)
594
+ graph = RailsForge::Graph.new
595
+ graph.generate
596
+ rescue => e
597
+ puts "Error: #{e.message}"
598
+ exit 1
599
+ end
600
+
601
+ # Handle wizard command
602
+ def self.handle_wizard_command(args)
603
+ # Check for --tty or --text flag
604
+ use_tty = !args.include?("--text") && ENV.fetch("FORCE_TTY", nil) != "false"
605
+
606
+ # Try to use TTY wizard if available
607
+ if use_tty
608
+ begin
609
+ require "tty-prompt"
610
+ tui = RailsForge::WizardTUI.new
611
+ tui.run
612
+ return
613
+ rescue LoadError
614
+ puts "TTY::Prompt not available, falling back to text wizard..."
615
+ rescue => e
616
+ puts "Warning: TUI failed (#{e.message}), falling back..."
617
+ end
618
+ end
619
+
620
+ # Fall back to text-based wizard
621
+ wizard = RailsForge::Wizard.new
622
+ options = wizard.run
623
+ print "\nCreate this project? (y/N): "
624
+ answer = STDIN.gets.strip.downcase
625
+ if answer == "y" || answer == "yes"
626
+ wizard.execute
627
+ else
628
+ puts "Cancelled."
629
+ end
630
+ rescue => e
631
+ puts "Error: #{e.message}"
632
+ exit 1
633
+ end
634
+
635
+ # Handle plugins command
636
+ def self.handle_plugins_command(args)
637
+ action = args.shift
638
+
639
+ case action
640
+ when nil, "list", "ls"
641
+ RailsForge::Plugins.show_installed
642
+ when "load"
643
+ RailsForge::Plugins.load(args.shift)
644
+ when "create"
645
+ RailsForge::Plugins.create(args.shift)
646
+ else
647
+ puts "Usage: railsforge plugins [list|load|create]"
648
+ end
649
+ end
650
+
651
+ # Handle config command
652
+ def self.handle_config_command(args)
653
+ action = args.shift
654
+
655
+ case action
656
+ when nil, "show"
657
+ RailsForge::Config.show
658
+ when "init"
659
+ RailsForge::Config.init
660
+ when "get"
661
+ puts RailsForge::Config.get(args.shift)
662
+ when "set"
663
+ RailsForge::Config.set(args.shift, args.shift)
664
+ when "reset"
665
+ RailsForge::Config.reset
666
+ else
667
+ puts "Usage: railsforge config [show|init|get|set|reset]"
668
+ end
669
+ end
670
+ end
671
+ end