belt 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9236fac00b7efcb43f17c02fb347626f768cf7dd5d6c1d2162470176043cdfde
4
- data.tar.gz: d7998c44bfcdfa42eb4d22acca3fabf62e0005753b355f4112bbdff108682527
3
+ metadata.gz: b12c5b4c22f46e0d4c80c10de7ee88f41bbcbb8a8e14a68b9033d19979a6c5af
4
+ data.tar.gz: d699a6f241fb01a111545450cb024d409e099d9e8617b788eee6fa1a47021a20
5
5
  SHA512:
6
- metadata.gz: 3ec40527e1d14fe89e8e5f3dc412e803354630126d40e9bed1a8c1dc32703ecd5a1fbffec1690ff0262ee2d1ece1895751441fc554f2cc38b86cb1d36e8b4ea8
7
- data.tar.gz: 3eaff9879994c9d2b7c3eb6b454a833bc4ae433bd544ac0c8fa3578045de96263a2871915b60d8707eaed8b512e497c88125554b45068d597d19d612a6b87209
6
+ metadata.gz: c1a17ba50a432b6f84103129394524c1fcaf40abadc89eb59dec7dd93b9e68ef6fda35444c45486c06f030d123816c7ac99b4d7b9320ba02485d9b70716cdb46
7
+ data.tar.gz: dab18cbb83517e05e404755923b6ce90dd45a8e155516e07649c63285f83f7ef0ec3d5cc8d62f9f7dd08553f8596d5ed0bb0298fc687a8167c0482bee44492dd
data/README.md CHANGED
@@ -34,6 +34,8 @@ my-app/
34
34
  │ ├── routes.tf.rb # Belt provider route definitions
35
35
  │ └── schema.tf.rb # DynamoDB table schemas
36
36
  ├── lambda/
37
+ │ ├── config/
38
+ │ │ └── environment.rb # App boot file (used by console + Lambda)
37
39
  │ ├── controllers/
38
40
  │ │ └── posts_controller.rb
39
41
  │ ├── models/
@@ -41,6 +43,7 @@ my-app/
41
43
  │ ├── lib/
42
44
  │ │ └── routes.rb
43
45
  │ └── api.rb # Lambda entry point
46
+ ├── .irbrc # Console customization (optional)
44
47
  ├── Gemfile
45
48
  └── Gemfile.lock
46
49
  ```
@@ -229,6 +232,22 @@ Belt::Observability::Metrics.track_event("OrderCreated", model: "Order")
229
232
 
230
233
  Belt includes a command-line interface for project management.
231
234
 
235
+ ### `belt console` (alias: `belt c`)
236
+
237
+ Start an interactive Ruby console with your app loaded. Belt uses convention over configuration:
238
+
239
+ 1. Loads `lambda/config/environment.rb` (your app's boot file — AWS setup, models, libs)
240
+ 2. Starts IRB with `reload!` available
241
+ 3. Reads `.irbrc` from the project root (console-specific customization)
242
+
243
+ ```bash
244
+ belt console # uses BELT_ENV or defaults to 'dev'
245
+ belt c prod # specify environment explicitly
246
+ belt c dev02 --run "Customer.first" # runner mode (execute and exit)
247
+ ```
248
+
249
+ A production safety prompt is shown when the environment is `prod`.
250
+
232
251
  ### `belt routes`
233
252
 
234
253
  Display route definitions from your `infrastructure/routes.tf.rb`. This is the primary way to inspect what endpoints your app exposes.
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+
5
+ module Belt
6
+ module CLI
7
+ class ConsoleCommand
8
+ def self.run(args)
9
+ new(args).run
10
+ end
11
+
12
+ def initialize(args)
13
+ @args = args
14
+ @options = {}
15
+ parse_options
16
+ end
17
+
18
+ def run
19
+ ENV['BUNDLE_GEMFILE'] ||= File.join(Belt.root, 'Gemfile')
20
+
21
+ unless File.exist?(ENV['BUNDLE_GEMFILE'])
22
+ abort "Error: No Gemfile found at #{ENV['BUNDLE_GEMFILE']}. Are you in a Belt project?"
23
+ end
24
+
25
+ @environment = @args.first || ENV['BELT_ENV'] || 'dev'
26
+ ENV['ENVIRONMENT'] = @environment
27
+
28
+ if @options[:run]
29
+ exec_runner(@options[:run])
30
+ else
31
+ exec_console
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def parse_options
38
+ OptionParser.new do |opts|
39
+ opts.banner = 'Usage: belt console [environment] [options]'
40
+ opts.on('--run COMMAND', 'Execute a command and exit') { |cmd| @options[:run] = cmd }
41
+ opts.on('-h', '--help', 'Show this help') do
42
+ puts opts
43
+ exit
44
+ end
45
+ end.parse!(@args)
46
+ end
47
+
48
+ def exec_console
49
+ production_guard!
50
+ boot_app
51
+ puts banner
52
+ ARGV.clear
53
+ require 'irb'
54
+ IRB.start
55
+ end
56
+
57
+ def exec_runner(command)
58
+ boot_app
59
+ result = eval(command) # rubocop:disable Security/Eval
60
+ puts format_result(result)
61
+ rescue StandardError => e
62
+ abort "Error: #{e.class}: #{e.message}\n#{e.backtrace.first(5).join("\n")}"
63
+ end
64
+
65
+ def boot_app
66
+ require 'bundler/setup'
67
+
68
+ environment_file = File.join(Belt.root, 'lambda', 'config', 'environment.rb')
69
+ if File.exist?(environment_file)
70
+ load environment_file
71
+ else
72
+ require 'belt'
73
+ load_dir('lib')
74
+ load_dir('models')
75
+ end
76
+
77
+ define_reload!
78
+ end
79
+
80
+ def load_dir(subdir)
81
+ dir = File.join(Belt.root, 'lambda', subdir)
82
+ Dir.glob(File.join(dir, '**', '*.rb')).each { |f| require f } if Dir.exist?(dir)
83
+ end
84
+
85
+ def define_reload!
86
+ root = Belt.root
87
+ Kernel.define_method(:reload!) do
88
+ %w[lib models].each do |subdir|
89
+ dir = File.join(root, 'lambda', subdir)
90
+ Dir.glob(File.join(dir, '**', '*.rb')).each { |f| load f } if Dir.exist?(dir)
91
+ end
92
+ puts '♻️ Reloaded'
93
+ end
94
+ end
95
+
96
+ def production_guard!
97
+ return unless @environment == 'prod'
98
+
99
+ $stdout.write "\n⚠️ WARNING: You are entering the PRODUCTION console!\nType 'yes' to continue: "
100
+ response = $stdin.gets&.chomp
101
+ abort "\n❌ Cancelled." unless response&.downcase == 'yes'
102
+ puts "\n✅ Entering production console...\n"
103
+ end
104
+
105
+ def banner
106
+ <<~BANNER
107
+
108
+ Belt Console (#{@environment})
109
+ Type 'reload!' to reload code.
110
+
111
+ BANNER
112
+ end
113
+
114
+ def format_result(result)
115
+ require 'json'
116
+ if result.respond_to?(:to_h)
117
+ JSON.pretty_generate(result.to_h)
118
+ elsif result.respond_to?(:map) && result.respond_to?(:first) && result.first.respond_to?(:to_h)
119
+ JSON.pretty_generate(result.map(&:to_h))
120
+ elsif result.nil?
121
+ 'nil'
122
+ else
123
+ result.inspect
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -71,6 +71,7 @@ module Belt
71
71
  #{@app_name}/lambda/models
72
72
  #{@app_name}/lambda/models/concerns
73
73
  #{@app_name}/lambda/lib/routes
74
+ #{@app_name}/lambda/config
74
75
  #{@app_name}/lambda/spec
75
76
  #{@app_name}/infrastructure
76
77
  ]
@@ -80,8 +81,8 @@ module Belt
80
81
  {
81
82
  'Gemfile.erb' => "#{@app_name}/Gemfile",
82
83
  'Rakefile.erb' => "#{@app_name}/Rakefile",
83
- 'lambda/Gemfile.erb' => "#{@app_name}/lambda/Gemfile",
84
84
  'lambda/api.rb.erb' => "#{@app_name}/lambda/#{@app_name}.rb",
85
+ 'lambda/config/environment.rb.erb' => "#{@app_name}/lambda/config/environment.rb",
85
86
  'lambda/models/application_record.rb.erb' => "#{@app_name}/lambda/models/application_record.rb",
86
87
  'lambda/models/concerns/timestampable.rb.erb' => "#{@app_name}/lambda/models/concerns/timestampable.rb",
87
88
  'lambda/controllers/application_controller.rb.erb' =>
@@ -16,13 +16,7 @@ module Belt
16
16
 
17
17
  return non_param.map { |s| s.gsub('-', '_') }.join('/') if route.resource? && nested_resource?(segments)
18
18
 
19
- if route.resource?
20
- non_param.first.gsub('-', '_')
21
- elsif non_param.length == 1 && segments.length == 1
22
- route.lambda.to_s == gateway.name.to_s ? gateway.name.to_s : route.lambda.to_s
23
- else
24
- non_param.first.gsub('-', '_')
25
- end
19
+ non_param.first.gsub('-', '_')
26
20
  end
27
21
 
28
22
  def infer_action(route, _gateway)
data/lib/belt/cli.rb CHANGED
@@ -13,6 +13,7 @@ require_relative 'cli/setup_command'
13
13
  require_relative 'cli/terraform_command'
14
14
  require_relative 'cli/routes_command'
15
15
  require_relative 'cli/tasks_command'
16
+ require_relative 'cli/console_command'
16
17
 
17
18
  module Belt
18
19
  module CLI
@@ -20,6 +21,7 @@ module Belt
20
21
  'new' => Belt::CLI::NewCommand,
21
22
  %w[generate g] => Belt::CLI::GenerateCommand,
22
23
  'routes' => Belt::CLI::RoutesCommand,
24
+ %w[console c] => Belt::CLI::ConsoleCommand,
23
25
  %w[tasks --tasks -T] => Belt::CLI::TasksCommand,
24
26
  'setup' => Belt::CLI::SetupCommand,
25
27
  'deploy' => lambda { |args|
@@ -79,6 +81,8 @@ module Belt
79
81
  generate views <resource> [fields...] Generate React pages for REST actions
80
82
  generate environment <name> Create a new environment
81
83
  routes [-g PATTERN] [-f json] Show route definitions
84
+ console Start an interactive console (IRB)
85
+ c Alias for console
82
86
  tasks [-g PATTERN] [-a] List available rake tasks
83
87
  -T [-g PATTERN] [-a] Alias for tasks
84
88
  setup state Create/select S3 state bucket
data/lib/belt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Belt
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.3'
5
5
  end
@@ -2,4 +2,6 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
+ gem 'activeitem'
5
6
  gem 'belt'
7
+ gem 'lambda_loadout'
@@ -1,13 +1,13 @@
1
1
  /.bundle
2
2
  /vendor/bundle
3
3
  *.gem
4
- Gemfile.lock
5
4
 
6
5
  # Terraform
7
6
  .terraform/
8
7
  *.tfstate
9
8
  *.tfstate.backup
10
9
  .terraform.lock.hcl
10
+ *.tfvars
11
11
 
12
12
  # Lambda build artifacts
13
13
  /lambda/vendor/
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Boot the application. Used by `belt console` and Lambda at runtime.
4
+
5
+ require 'belt'
6
+ require 'activeitem'
7
+
8
+ ENV['APP_NAME'] ||= '<%= @app_name %>'
9
+ ENV['AWS_REGION'] ||= 'us-east-1'
10
+
11
+ ActiveItem.configure do |config|
12
+ config.table_prefix = ENV['APP_NAME']
13
+ config.environment = ENV['ENVIRONMENT']
14
+ end
15
+
16
+ # Load lib and models
17
+ Dir[File.join(__dir__, '..', 'lib', '**', '*.rb')].sort.each { |f| require f }
18
+ Dir[File.join(__dir__, '..', 'models', '**', '*.rb')].sort.each { |f| require f }
metadata CHANGED
@@ -1,39 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: belt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stowzilla
8
8
  bindir: exe
9
- cert_chain:
10
- - |
11
- -----BEGIN CERTIFICATE-----
12
- MIIEdDCCAtygAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMQ4wDAYDVQQDDAVhZ2Vu
13
- dDEZMBcGCgmSJomT8ixkARkWCXN0b3d6aWxsYTETMBEGCgmSJomT8ixkARkWA2Nv
14
- bTAeFw0yNjA2MDgxOTExNTlaFw0yNzA2MDgxOTExNTlaMEAxDjAMBgNVBAMMBWFn
15
- ZW50MRkwFwYKCZImiZPyLGQBGRYJc3Rvd3ppbGxhMRMwEQYKCZImiZPyLGQBGRYD
16
- Y29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAupBquKI/4WvXOgND
17
- pXyqH2GllZs1wG4TWWdn/DoMg45UoCwD+AWEuGrIdInBCpPN8vEJNJWPoM/RrU+b
18
- xRBZT4uUk00bnZRW2SYh5GJSqBoBR+rWc2DGkXyGfdRU2sQvkB0+is6ChgQ61WMM
19
- 33LE9+loBlVsZ6EVtrc18Uh2OW0mJpe0hN2nmBrxZqqOZigxC4DKRMFHvpRkxSb6
20
- mD4kit1AcwX9NEWJsXxrPaetL/SB/VbXaEZX93XAvp6USaXvCWt4slkDS2mIvqtn
21
- 9DtGC43LFC7SDGbnsG9PVenQgVCi8UWFPUAab0PqZSlmi3Qlbhw8qTGPp5Cbv4vz
22
- qjC2UGPOQigA/7lbbGRhCohMrjOVHMAQwkcgiIqtolUoYlnvPMIy+m3pdvgDv/PH
23
- bsZGvXQ7i0458xsmp1vaKthZocVAR+GboHbuIiYPUnO45ccXUQ00x6365tTe7mZi
24
- NvmUYdAGbQmVvFqyxF7IYA6sF74L2Lstu0knSfss557bAe1HAgMBAAGjeTB3MAkG
25
- A1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSnxTL/lNBCeLqpeVIX6AUY
26
- kel4zjAeBgNVHREEFzAVgRNhZ2VudEBzdG93emlsbGEuY29tMB4GA1UdEgQXMBWB
27
- E2FnZW50QHN0b3d6aWxsYS5jb20wDQYJKoZIhvcNAQELBQADggGBACm9Fjit/UCv
28
- FxlKqeiCTIG94cIx+QrWAOJSx9knKydwUec1u04D/DbfZjTn3C2Bj227QgxeUn+6
29
- if3e2v7zAk1896hLmGYzML0+nxQPb0vmtdLR7HETUlSKTVabcv1fbwLyjsuGrBvk
30
- y51vOEzUEZ508a9yepLYqrQu1kOju4d57c9oA5l3H0mMKWz7av9tFj0B+STvuaWk
31
- HRYDWc5HgOEVTyV+w0uFt2Kw4OCb8C42uSvC5RfYYtw78MSP+5Ru+LXJ7XOtmuN0
32
- E6GVmofQ17ig9O3rgfFbMendSInrRmvPIGswvM1yivq9NOllFbdck2OJKPx6FCJF
33
- 7SJIkXQfc9P4B5iASIV1d1FsE0YX+g3jHXPJK/4mGL5bAyBKzpMfQB/mg6vQBzkh
34
- aOKPwcreFj7TznBl89R5tNS9wZQfPVR98zgPyocddWhK18eQNMSBUnv4eeJ8PPbk
35
- DovL+G8ajHDZ9fjH/+GVYHEMuiVdLarXrKJpHC1VfGTTUAp4NSEpUQ==
36
- -----END CERTIFICATE-----
9
+ cert_chain: []
37
10
  date: 1980-01-02 00:00:00.000000000 Z
38
11
  dependencies:
39
12
  - !ruby/object:Gem::Dependency
@@ -76,13 +49,13 @@ files:
76
49
  - CHANGELOG.md
77
50
  - LICENSE.txt
78
51
  - README.md
79
- - certs/stowzilla.pem
80
52
  - exe/belt
81
53
  - lib/belt.rb
82
54
  - lib/belt/action_router.rb
83
55
  - lib/belt/cli.rb
84
56
  - lib/belt/cli/app_detection.rb
85
57
  - lib/belt/cli/bucket_security.rb
58
+ - lib/belt/cli/console_command.rb
86
59
  - lib/belt/cli/env_resolver.rb
87
60
  - lib/belt/cli/environment_command.rb
88
61
  - lib/belt/cli/frontend_command.rb
@@ -131,8 +104,8 @@ files:
131
104
  - lib/templates/new_app/gitignore.erb
132
105
  - lib/templates/new_app/infrastructure/routes.tf.rb.erb
133
106
  - lib/templates/new_app/infrastructure/schema.tf.rb.erb
134
- - lib/templates/new_app/lambda/Gemfile.erb
135
107
  - lib/templates/new_app/lambda/api.rb.erb
108
+ - lib/templates/new_app/lambda/config/environment.rb.erb
136
109
  - lib/templates/new_app/lambda/controllers/application_controller.rb.erb
137
110
  - lib/templates/new_app/lambda/lib/routes/routes.rb.erb
138
111
  - lib/templates/new_app/lambda/models/application_record.rb.erb
checksums.yaml.gz.sig DELETED
@@ -1 +0,0 @@
1
- �X\h��3ʙk�e���s���V���EB�p�:y1͸��M�dŸz(�j���{�n����騐��Լ ;:�db���Ŵ����H�j$S8/������p���E��������|3��^���5 œ��|�%��NΛ(7P�`A#��v���j�v{�%]��R�%�-<Lܟ��2���K��9�[�Ÿ�ud��ęl���:t ��̱����#�Z�Ҏ�Ok��>��@vV����;A�8����=rՇ���iy}���p9b��`�c"vl,�r$��{>�䷹��v�ͮ���ȗ������ܡ�="�r��(�,�:�S�`��«��Vl~� �&Y�%�N��V�Dtf-���N[�Q���
data/certs/stowzilla.pem DELETED
@@ -1,26 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEdDCCAtygAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMQ4wDAYDVQQDDAVhZ2Vu
3
- dDEZMBcGCgmSJomT8ixkARkWCXN0b3d6aWxsYTETMBEGCgmSJomT8ixkARkWA2Nv
4
- bTAeFw0yNjA2MDgxOTExNTlaFw0yNzA2MDgxOTExNTlaMEAxDjAMBgNVBAMMBWFn
5
- ZW50MRkwFwYKCZImiZPyLGQBGRYJc3Rvd3ppbGxhMRMwEQYKCZImiZPyLGQBGRYD
6
- Y29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAupBquKI/4WvXOgND
7
- pXyqH2GllZs1wG4TWWdn/DoMg45UoCwD+AWEuGrIdInBCpPN8vEJNJWPoM/RrU+b
8
- xRBZT4uUk00bnZRW2SYh5GJSqBoBR+rWc2DGkXyGfdRU2sQvkB0+is6ChgQ61WMM
9
- 33LE9+loBlVsZ6EVtrc18Uh2OW0mJpe0hN2nmBrxZqqOZigxC4DKRMFHvpRkxSb6
10
- mD4kit1AcwX9NEWJsXxrPaetL/SB/VbXaEZX93XAvp6USaXvCWt4slkDS2mIvqtn
11
- 9DtGC43LFC7SDGbnsG9PVenQgVCi8UWFPUAab0PqZSlmi3Qlbhw8qTGPp5Cbv4vz
12
- qjC2UGPOQigA/7lbbGRhCohMrjOVHMAQwkcgiIqtolUoYlnvPMIy+m3pdvgDv/PH
13
- bsZGvXQ7i0458xsmp1vaKthZocVAR+GboHbuIiYPUnO45ccXUQ00x6365tTe7mZi
14
- NvmUYdAGbQmVvFqyxF7IYA6sF74L2Lstu0knSfss557bAe1HAgMBAAGjeTB3MAkG
15
- A1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSnxTL/lNBCeLqpeVIX6AUY
16
- kel4zjAeBgNVHREEFzAVgRNhZ2VudEBzdG93emlsbGEuY29tMB4GA1UdEgQXMBWB
17
- E2FnZW50QHN0b3d6aWxsYS5jb20wDQYJKoZIhvcNAQELBQADggGBACm9Fjit/UCv
18
- FxlKqeiCTIG94cIx+QrWAOJSx9knKydwUec1u04D/DbfZjTn3C2Bj227QgxeUn+6
19
- if3e2v7zAk1896hLmGYzML0+nxQPb0vmtdLR7HETUlSKTVabcv1fbwLyjsuGrBvk
20
- y51vOEzUEZ508a9yepLYqrQu1kOju4d57c9oA5l3H0mMKWz7av9tFj0B+STvuaWk
21
- HRYDWc5HgOEVTyV+w0uFt2Kw4OCb8C42uSvC5RfYYtw78MSP+5Ru+LXJ7XOtmuN0
22
- E6GVmofQ17ig9O3rgfFbMendSInrRmvPIGswvM1yivq9NOllFbdck2OJKPx6FCJF
23
- 7SJIkXQfc9P4B5iASIV1d1FsE0YX+g3jHXPJK/4mGL5bAyBKzpMfQB/mg6vQBzkh
24
- aOKPwcreFj7TznBl89R5tNS9wZQfPVR98zgPyocddWhK18eQNMSBUnv4eeJ8PPbk
25
- DovL+G8ajHDZ9fjH/+GVYHEMuiVdLarXrKJpHC1VfGTTUAp4NSEpUQ==
26
- -----END CERTIFICATE-----
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- gem 'activeitem'
6
- gem 'belt'
7
- gem 'lambda_loadout'
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
Binary file