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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +528 -0
- data/bin/railsforge +8 -0
- data/lib/railsforge/analyzers/base_analyzer.rb +41 -0
- data/lib/railsforge/analyzers/controller_analyzer.rb +83 -0
- data/lib/railsforge/analyzers/database_analyzer.rb +55 -0
- data/lib/railsforge/analyzers/metrics_analyzer.rb +55 -0
- data/lib/railsforge/analyzers/model_analyzer.rb +74 -0
- data/lib/railsforge/analyzers/performance_analyzer.rb +161 -0
- data/lib/railsforge/analyzers/refactor_analyzer.rb +118 -0
- data/lib/railsforge/analyzers/security_analyzer.rb +169 -0
- data/lib/railsforge/analyzers/spec_analyzer.rb +58 -0
- data/lib/railsforge/api_generator.rb +397 -0
- data/lib/railsforge/audit.rb +289 -0
- data/lib/railsforge/cli.rb +671 -0
- data/lib/railsforge/config.rb +181 -0
- data/lib/railsforge/database_analyzer.rb +300 -0
- data/lib/railsforge/doctor.rb +250 -0
- data/lib/railsforge/feature_generator.rb +560 -0
- data/lib/railsforge/generator.rb +313 -0
- data/lib/railsforge/generators/base_generator.rb +70 -0
- data/lib/railsforge/generators/demo_generator.rb +307 -0
- data/lib/railsforge/generators/devops_generator.rb +287 -0
- data/lib/railsforge/generators/monitoring_generator.rb +134 -0
- data/lib/railsforge/generators/service_generator.rb +122 -0
- data/lib/railsforge/generators/stimulus_controller_generator.rb +129 -0
- data/lib/railsforge/generators/test_generator.rb +289 -0
- data/lib/railsforge/generators/view_component_generator.rb +169 -0
- data/lib/railsforge/graph.rb +270 -0
- data/lib/railsforge/loader.rb +56 -0
- data/lib/railsforge/mailer_generator.rb +191 -0
- data/lib/railsforge/plugins/plugin_loader.rb +60 -0
- data/lib/railsforge/plugins.rb +30 -0
- data/lib/railsforge/profiles/admin_app.yml +49 -0
- data/lib/railsforge/profiles/api_only.yml +47 -0
- data/lib/railsforge/profiles/blog.yml +47 -0
- data/lib/railsforge/profiles/standard.yml +44 -0
- data/lib/railsforge/profiles.rb +99 -0
- data/lib/railsforge/refactor_analyzer.rb +401 -0
- data/lib/railsforge/refactor_controller.rb +277 -0
- data/lib/railsforge/refactors/refactor_controller.rb +117 -0
- data/lib/railsforge/template_loader.rb +105 -0
- data/lib/railsforge/templates/v1/form/spec_template.rb +18 -0
- data/lib/railsforge/templates/v1/form/template.rb +28 -0
- data/lib/railsforge/templates/v1/job/spec_template.rb +17 -0
- data/lib/railsforge/templates/v1/job/template.rb +13 -0
- data/lib/railsforge/templates/v1/policy/spec_template.rb +41 -0
- data/lib/railsforge/templates/v1/policy/template.rb +57 -0
- data/lib/railsforge/templates/v1/presenter/spec_template.rb +12 -0
- data/lib/railsforge/templates/v1/presenter/template.rb +13 -0
- data/lib/railsforge/templates/v1/query/spec_template.rb +12 -0
- data/lib/railsforge/templates/v1/query/template.rb +16 -0
- data/lib/railsforge/templates/v1/serializer/spec_template.rb +13 -0
- data/lib/railsforge/templates/v1/serializer/template.rb +11 -0
- data/lib/railsforge/templates/v1/service/spec_template.rb +12 -0
- data/lib/railsforge/templates/v1/service/template.rb +25 -0
- data/lib/railsforge/templates/v1/stimulus_controller/template.rb +35 -0
- data/lib/railsforge/templates/v1/view_component/template.rb +24 -0
- data/lib/railsforge/templates/v2/job/template.rb +49 -0
- data/lib/railsforge/templates/v2/query/template.rb +66 -0
- data/lib/railsforge/templates/v2/service/spec_template.rb +33 -0
- data/lib/railsforge/templates/v2/service/template.rb +71 -0
- data/lib/railsforge/templates/v3/job/template.rb +72 -0
- data/lib/railsforge/templates/v3/query/spec_template.rb +54 -0
- data/lib/railsforge/templates/v3/query/template.rb +115 -0
- data/lib/railsforge/templates/v3/service/spec_template.rb +51 -0
- data/lib/railsforge/templates/v3/service/template.rb +84 -0
- data/lib/railsforge/version.rb +5 -0
- data/lib/railsforge/wizard.rb +265 -0
- data/lib/railsforge/wizard_tui.rb +286 -0
- data/lib/railsforge.rb +13 -0
- 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
|