belt 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/belt/cli/destroy_command.rb +12 -2
- data/lib/belt/cli/frontend_env_map.rb +1 -1
- data/lib/belt/cli/generate_command.rb +27 -2
- data/lib/belt/cli/generator_registry.rb +92 -0
- data/lib/belt/cli.rb +1 -1
- data/lib/belt/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3834960aad8c883c22d15acec6a320d860bd8b90acb3c7c74751c59ce49b959
|
|
4
|
+
data.tar.gz: 29f96098a7ac79c0f3eb62edd9950a9d1e95e2f56b219b3fcd024b19f3b4daac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 597c85007b7e8838f77605ec31de2b20bac85bf29ec20de371b85f03dd4a9eb20abba6be12f5b8f701e2c36ee02377b3488efa00292060f36b8bc956ef04d8ed
|
|
7
|
+
data.tar.gz: 4c24a2f2c554244010ec246bc337194f6616ed04394ff8aeea4d5aabe91c97adeac7aaad76fbfa9a812fa35397fc46770c347ee590a5d307e2073ee2e811ff13
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.13
|
|
4
|
+
|
|
5
|
+
### Generator Extension API
|
|
6
|
+
|
|
7
|
+
- Gems can now register generators by placing a file at `lib/belt/generators/<name>_generator.rb`.
|
|
8
|
+
- Discovered automatically via `Gem.loaded_specs` — no manual registration needed.
|
|
9
|
+
- Available as `belt generate <name>` / `belt destroy <name>`.
|
|
10
|
+
- Generator contract: `.run(args)` (required), `.destroy(args)` (optional), `.description` (optional).
|
|
11
|
+
- Help output includes gem-provided generators under "Gem Generators" section.
|
|
12
|
+
|
|
3
13
|
## Unreleased
|
|
4
14
|
|
|
5
15
|
## 0.1.11
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'fileutils'
|
|
4
4
|
require_relative 'app_detection'
|
|
5
|
+
require_relative 'generator_registry'
|
|
5
6
|
require_relative 'tables_command'
|
|
6
7
|
require_relative '../inflector'
|
|
7
8
|
|
|
@@ -20,13 +21,22 @@ module Belt
|
|
|
20
21
|
exit 0
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
unless GENERATORS.include?(generator)
|
|
24
|
+
unless GENERATORS.include?(generator) || GeneratorRegistry.generator_names.include?(generator)
|
|
24
25
|
puts "Unknown generator: '#{generator}'"
|
|
25
|
-
puts "Available: #{GENERATORS.uniq.join(', ')}"
|
|
26
|
+
puts "Available: #{(GENERATORS + GeneratorRegistry.generator_names).uniq.join(', ')}"
|
|
26
27
|
puts "\nRun 'belt destroy --help' for usage information."
|
|
27
28
|
exit 1
|
|
28
29
|
end
|
|
29
30
|
|
|
31
|
+
# Delegate to gem-provided generator if not a built-in
|
|
32
|
+
unless GENERATORS.include?(generator)
|
|
33
|
+
klass = GeneratorRegistry.find(generator)
|
|
34
|
+
return klass.destroy(args) if klass.respond_to?(:destroy)
|
|
35
|
+
|
|
36
|
+
puts "Generator '#{generator}' does not support destroy."
|
|
37
|
+
exit 1
|
|
38
|
+
end
|
|
39
|
+
|
|
30
40
|
# Normalize: resource is an alias for scaffold
|
|
31
41
|
generator = 'scaffold' if generator == 'resource'
|
|
32
42
|
|
|
@@ -7,6 +7,7 @@ require_relative 'environment_command'
|
|
|
7
7
|
require_relative 'frontend_command'
|
|
8
8
|
require_relative 'tables_command'
|
|
9
9
|
require_relative 'views_command'
|
|
10
|
+
require_relative 'generator_registry'
|
|
10
11
|
require_relative '../inflector'
|
|
11
12
|
|
|
12
13
|
module Belt
|
|
@@ -84,13 +85,19 @@ module Belt
|
|
|
84
85
|
exit 0
|
|
85
86
|
end
|
|
86
87
|
|
|
87
|
-
unless GENERATORS.include?(generator)
|
|
88
|
+
unless GENERATORS.include?(generator) || GeneratorRegistry.generator_names.include?(generator)
|
|
88
89
|
puts "Unknown generator: '#{generator}'"
|
|
89
|
-
puts "Available generators: #{
|
|
90
|
+
puts "Available generators: #{all_generator_names.join(', ')}"
|
|
90
91
|
puts "\nRun 'belt generate --help' for usage information."
|
|
91
92
|
exit 1
|
|
92
93
|
end
|
|
93
94
|
|
|
95
|
+
# Delegate to gem-provided generator if not a built-in
|
|
96
|
+
unless GENERATORS.include?(generator)
|
|
97
|
+
klass = GeneratorRegistry.find(generator)
|
|
98
|
+
return klass.run(args)
|
|
99
|
+
end
|
|
100
|
+
|
|
94
101
|
# Normalize: resource is an alias for scaffold
|
|
95
102
|
generator = 'scaffold' if generator == 'resource'
|
|
96
103
|
|
|
@@ -131,6 +138,10 @@ module Belt
|
|
|
131
138
|
belt setup environment frontend views routes
|
|
132
139
|
].freeze
|
|
133
140
|
|
|
141
|
+
def self.all_generator_names
|
|
142
|
+
((GENERATORS - ['resource']) + GeneratorRegistry.generator_names).uniq
|
|
143
|
+
end
|
|
144
|
+
|
|
134
145
|
def self.validate_resource_name!(name, generator)
|
|
135
146
|
errors = []
|
|
136
147
|
|
|
@@ -152,6 +163,8 @@ module Belt
|
|
|
152
163
|
end
|
|
153
164
|
|
|
154
165
|
def self.print_generate_help
|
|
166
|
+
gem_generators = GeneratorRegistry.discovered_generators
|
|
167
|
+
|
|
155
168
|
puts <<~HELP
|
|
156
169
|
Usage: belt generate <generator> <name> [field:type ...] [options]
|
|
157
170
|
belt g <generator> <name> [field:type ...] [options]
|
|
@@ -167,6 +180,18 @@ module Belt
|
|
|
167
180
|
Aliases:
|
|
168
181
|
resource Same as scaffold
|
|
169
182
|
|
|
183
|
+
HELP
|
|
184
|
+
|
|
185
|
+
if gem_generators.any?
|
|
186
|
+
puts ' Gem Generators:'
|
|
187
|
+
gem_generators.each do |name, klass|
|
|
188
|
+
desc = klass.respond_to?(:description) ? klass.description : "Generate #{name} (from gem)"
|
|
189
|
+
puts format(' %<name>-14s %<desc>s', name: name, desc: desc)
|
|
190
|
+
end
|
|
191
|
+
puts
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
puts <<~HELP
|
|
170
195
|
Field Types:
|
|
171
196
|
#{FIELD_TYPES.join(', ')}
|
|
172
197
|
(defaults to string if omitted)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Belt
|
|
4
|
+
module CLI
|
|
5
|
+
# Discovers and manages generators provided by external gems.
|
|
6
|
+
#
|
|
7
|
+
# Gems register generators by placing a file at:
|
|
8
|
+
# lib/belt/generators/<name>_generator.rb
|
|
9
|
+
#
|
|
10
|
+
# Each generator class must:
|
|
11
|
+
# - Be named <Name>Generator (e.g., MessagingGenerator)
|
|
12
|
+
# - Live in the Belt::Generators module
|
|
13
|
+
# - Implement .run(args) for generation
|
|
14
|
+
# - Implement .destroy(args) for teardown (optional)
|
|
15
|
+
# - Implement .description for help text (optional)
|
|
16
|
+
#
|
|
17
|
+
# Example gem structure:
|
|
18
|
+
# belt-messaging/
|
|
19
|
+
# lib/
|
|
20
|
+
# belt/
|
|
21
|
+
# generators/
|
|
22
|
+
# messaging_generator.rb
|
|
23
|
+
#
|
|
24
|
+
# The generator is then available as:
|
|
25
|
+
# belt generate messaging
|
|
26
|
+
# belt destroy messaging
|
|
27
|
+
#
|
|
28
|
+
module GeneratorRegistry
|
|
29
|
+
GENERATOR_PATH = 'lib/belt/generators'
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
# Returns a hash of { "name" => generator_class } for all discovered generators.
|
|
33
|
+
def discovered_generators
|
|
34
|
+
@discovered_generators ||= discover_all
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns just the names of discovered generators.
|
|
38
|
+
def generator_names
|
|
39
|
+
discovered_generators.keys
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Loads and returns the generator class for a given name.
|
|
43
|
+
# Returns nil if not found.
|
|
44
|
+
def find(name)
|
|
45
|
+
discovered_generators[name]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Reset cache (useful in tests)
|
|
49
|
+
def reset!
|
|
50
|
+
@discovered_generators = nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def discover_all
|
|
56
|
+
generators = {}
|
|
57
|
+
|
|
58
|
+
Gem.loaded_specs.each_value do |spec|
|
|
59
|
+
generators_dir = File.join(spec.gem_dir, GENERATOR_PATH)
|
|
60
|
+
next unless File.directory?(generators_dir)
|
|
61
|
+
|
|
62
|
+
Dir.glob(File.join(generators_dir, '*_generator.rb')).each do |file|
|
|
63
|
+
name = File.basename(file, '.rb').sub(/_generator\z/, '')
|
|
64
|
+
klass = load_generator_class(file, name)
|
|
65
|
+
generators[name] = klass if klass
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
generators
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def load_generator_class(file, name)
|
|
73
|
+
require file
|
|
74
|
+
|
|
75
|
+
class_name = "#{classify(name)}Generator"
|
|
76
|
+
Belt::Generators.const_get(class_name)
|
|
77
|
+
rescue LoadError, NameError => e
|
|
78
|
+
warn "[Belt] Warning: Failed to load generator '#{name}' from #{file}: #{e.message}"
|
|
79
|
+
nil
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def classify(name)
|
|
83
|
+
name.split('_').map(&:capitalize).join
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Namespace for generator classes provided by external gems
|
|
90
|
+
module Generators
|
|
91
|
+
end
|
|
92
|
+
end
|
data/lib/belt/cli.rb
CHANGED
|
@@ -56,7 +56,7 @@ module Belt
|
|
|
56
56
|
# belt destroy --help → DestroyCommand help
|
|
57
57
|
# belt destroy (no args) → terraform destroy (needs env)
|
|
58
58
|
return DestroyCommand.run(args) if args.include?('--help') || args.include?('-h')
|
|
59
|
-
elsif DestroyCommand::GENERATORS.include?(args.first)
|
|
59
|
+
elsif DestroyCommand::GENERATORS.include?(args.first) || GeneratorRegistry.generator_names.include?(args.first)
|
|
60
60
|
return DestroyCommand.run(args)
|
|
61
61
|
end
|
|
62
62
|
end
|
data/lib/belt/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: belt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stowzilla
|
|
@@ -82,6 +82,7 @@ files:
|
|
|
82
82
|
- lib/belt/cli/frontend_env_map.rb
|
|
83
83
|
- lib/belt/cli/frontend_setup_command.rb
|
|
84
84
|
- lib/belt/cli/generate_command.rb
|
|
85
|
+
- lib/belt/cli/generator_registry.rb
|
|
85
86
|
- lib/belt/cli/new_command.rb
|
|
86
87
|
- lib/belt/cli/routes_command.rb
|
|
87
88
|
- lib/belt/cli/routes_command/route_inference.rb
|