belt 0.3.4 → 0.3.5

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: 33ab3ee829508580c32a99fd91f008cd09b3dd80e2502f22b03e7e4d5ff9d00a
4
- data.tar.gz: 204c45931c8e038037f4d49781bbf43fff9396cd58e32d38d4cdb607fdccdfa7
3
+ metadata.gz: 803700aa6a859842c684ea0dc77b455a050698f1585663346e2c0aa1c057687a
4
+ data.tar.gz: b442f719e65920b93f1ba09eb841ba6498490645630576e8700d448073f21731
5
5
  SHA512:
6
- metadata.gz: 2f2f957782e6b03ef246167f46309a51a50cc286d3d4c1d8ba4411eba8a2ad558a2556986991848116519c5286bef5d57e5805307bbf314932580b82397beb43
7
- data.tar.gz: 587671ca7188c4ff9476ee4568b3f7f513c05eb285088be3b7282a1b2096b4cc7f6a3c7d7f1e609e92e22e87db851b785422fd0ab4ea07e76ecd028cf6b87103
6
+ metadata.gz: 6ebc34ade7cbbd8867330adbbe5c0ae2732719265d7afe1c080a4d9320c7d80e1dce316186f2de560bcda3df76ad8bdc4af31a2d7c3bd77d95c0dbd0c2fe41b5
7
+ data.tar.gz: 43abfb9e472722ca8728558edd91f2a41a8f77f5857d992528c915a35c36951f9b30548918d11f2a6291947714abd9f823049d22e3e3907ad850b16ae5c3331c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.3.5
6
+
7
+ ### Enhancement
8
+
9
+ - **Multiple frontends**: Frontend directory is no longer hardcoded to `frontend/`.
10
+ Declare named SPAs in `config/frontends.yml` (path, dist dir, terraform output names).
11
+ `belt generate frontend react --name ops --path ops-app` scaffolds an additional app.
12
+ Generators, `belt server`, `belt frontend env`, and `belt deploy frontend` accept
13
+ `--frontend NAME`. `belt deploy frontend <env>` deploys all configured frontends;
14
+ pass `--frontend` to target one. Existing single-`frontend/` apps keep working
15
+ with no config file.
16
+ - **Sidecar Lambda zips**: `belt deploy` / `belt plan` / `belt apply` build zip
17
+ artifacts that Terraform `filebase64sha256` needs at plan time (e.g. Stowzilla's
18
+ Node `image-processor`). Node packages are installed in Docker on linux/amd64
19
+ so native addons match Lambda. Missing zips are built automatically; unchanged
20
+ sources skip the rebuild.
21
+
22
+ ### Bug fix
23
+
24
+ - **Frontend CloudFront invalidation**: `belt deploy frontend` no longer prints
25
+ terraform's "output not found" error when a named frontend sets
26
+ `cloudfront_domain_output` instead of a distribution-id output. Missing
27
+ terraform outputs are read with stderr silenced.
28
+
3
29
  ## 0.3.4
4
30
 
5
31
  ### Enhancement
@@ -3,6 +3,7 @@
3
3
  require 'fileutils'
4
4
  require 'erb'
5
5
  require_relative 'app_detection'
6
+ require_relative 'frontend_registry'
6
7
 
7
8
  module Belt
8
9
  module CLI
@@ -20,13 +21,14 @@ module Belt
20
21
 
21
22
  force = args.delete('--force') || args.delete('-f')
22
23
  signup = args.delete('--signup')
24
+ frontend_name = FrontendRegistry.extract_flag!(args, '--frontend')
23
25
  pools = parse_pools(args)
24
26
 
25
- new(pools: pools, force: force, signup: signup).generate
27
+ new(pools: pools, force: force, signup: signup, frontend_name: frontend_name).generate
26
28
  end
27
29
 
28
30
  def self.destroy(_args)
29
- new(pools: [], force: false).remove
31
+ new(pools: [], force: false, skip_frontend_resolve: true).remove
30
32
  end
31
33
 
32
34
  def self.print_help
@@ -36,8 +38,9 @@ module Belt
36
38
  Usage: belt generate auth [pool_names...] [options]
37
39
 
38
40
  Options:
39
- --signup Allow public user registration (generates frontend views)
40
- --force, -f Overwrite existing cognito.tf (skip collision check)
41
+ --signup Allow public user registration (generates frontend views)
42
+ --frontend NAME Target frontend when several exist
43
+ --force, -f Overwrite existing cognito.tf (skip collision check)
41
44
 
42
45
  Arguments:
43
46
  pool_names Optional pool names for multiple user pools.
@@ -86,12 +89,13 @@ module Belt
86
89
  names.map(&:downcase).map { |n| n.gsub(/[^a-z0-9_]/, '_') }
87
90
  end
88
91
 
89
- def initialize(pools:, force: false, signup: false)
92
+ def initialize(pools:, force: false, signup: false, frontend_name: nil, skip_frontend_resolve: false)
90
93
  @pool_names = pools
91
94
  @force = force
92
95
  @signup = signup
93
96
  @app_name = detect_app_name
94
97
  @pools = build_pool_metadata
98
+ @frontend = skip_frontend_resolve ? nil : resolve_frontend(frontend_name)
95
99
  end
96
100
 
97
101
  def generate
@@ -117,7 +121,7 @@ module Belt
117
121
  puts ' end'
118
122
  puts ''
119
123
  if frontend?
120
- puts ' 2. Wire auth into your frontend/src/App.jsx:'
124
+ puts " 2. Wire auth into your #{@frontend.src_dir}/App.jsx:"
121
125
  puts ''
122
126
  puts " import Login from './pages/auth/Login'"
123
127
  puts " import ProtectedRoute from './components/ProtectedRoute'"
@@ -185,20 +189,30 @@ module Belt
185
189
  end
186
190
  end
187
191
 
192
+ def resolve_frontend(name)
193
+ registry = FrontendRegistry.new
194
+ return nil if registry.empty? && name.nil?
195
+
196
+ return registry.resolve!(name) if name
197
+
198
+ registry.default
199
+ end
200
+
188
201
  def frontend?
189
- Dir.exist?('frontend/src')
202
+ @frontend && Dir.exist?(@frontend.src_dir)
190
203
  end
191
204
 
192
205
  def generate_frontend_auth
193
206
  frontend_template_dir = File.join(TEMPLATE_DIR, 'frontend')
207
+ src = @frontend.src_dir
194
208
 
195
209
  # Generate auth lib files
196
- lib_dir = 'frontend/src/lib'
210
+ lib_dir = File.join(src, 'lib')
197
211
  FileUtils.mkdir_p(lib_dir)
198
212
  copy_frontend_file(frontend_template_dir, 'auth.js', File.join(lib_dir, 'auth.js'))
199
213
  copy_frontend_file(frontend_template_dir, 'apiClient.js', File.join(lib_dir, 'apiClient.js'))
200
214
 
201
- pages_dir = 'frontend/src/pages/auth'
215
+ pages_dir = File.join(src, 'pages/auth')
202
216
  FileUtils.mkdir_p(pages_dir)
203
217
  copy_frontend_file(frontend_template_dir, 'Login.jsx', File.join(pages_dir, 'Login.jsx'))
204
218
  copy_frontend_file(frontend_template_dir, 'auth.css', File.join(pages_dir, 'auth.css'))
@@ -209,7 +223,7 @@ module Belt
209
223
  end
210
224
 
211
225
  # Generate ProtectedRoute component
212
- components_dir = 'frontend/src/components'
226
+ components_dir = File.join(src, 'components')
213
227
  FileUtils.mkdir_p(components_dir)
214
228
  copy_frontend_file(frontend_template_dir, 'ProtectedRoute.jsx',
215
229
  File.join(components_dir, 'ProtectedRoute.jsx'))
@@ -226,11 +240,12 @@ module Belt
226
240
  def install_cognito_sdk
227
241
  puts "\n Installing @aws-sdk/client-cognito-identity-provider..."
228
242
  success = system('npm', 'install', '@aws-sdk/client-cognito-identity-provider',
229
- '--prefix', 'frontend', '--no-fund', '--no-audit', '--silent')
243
+ '--prefix', @frontend.path, '--no-fund', '--no-audit', '--silent')
230
244
  if success
231
245
  puts ' ✓ npm dependency installed'
232
246
  else
233
- puts ' ⚠ npm install failed — run: cd frontend && npm install @aws-sdk/client-cognito-identity-provider'
247
+ puts " ⚠ npm install failed — run: cd #{@frontend.path} && " \
248
+ 'npm install @aws-sdk/client-cognito-identity-provider'
234
249
  end
235
250
  end
236
251
 
@@ -10,6 +10,7 @@ require_relative 'backup_config'
10
10
  require_relative 'backup_runner'
11
11
  require_relative 'environment_config'
12
12
  require_relative 'path_gem_materializer'
13
+ require_relative 'zip_artifact_builder'
13
14
 
14
15
  module Belt
15
16
  module CLI
@@ -66,7 +67,8 @@ module Belt
66
67
  puts ' belt deploy prod # Deploy to prod'
67
68
  puts ' belt deploy dev --auto # Deploy without confirmation'
68
69
  puts ' belt deploy --rebuild # Fast code push (no infra changes)'
69
- puts ' belt deploy frontend dev # Deploy frontend only'
70
+ puts ' belt deploy frontend dev # Deploy frontend(s)'
71
+ puts ' belt deploy frontend dev --frontend ops'
70
72
  puts "\nNo environments found. Run `belt generate environment dev` first."
71
73
  exit 1
72
74
  end
@@ -92,10 +94,11 @@ module Belt
92
94
  1. Ensure Gemfile.lock is consistent (fix stale PATH refs)
93
95
  2. Regenerate route manifests
94
96
  3. Run pre-deploy backups (if configured in belt.rb)
95
- 4. terraform init (initialize providers/modules)
96
- 5. terraform plan (preview changes)
97
- 6. Prompt for confirmation (unless --auto)
98
- 7. terraform apply (deploy changes)
97
+ 4. Build sidecar Lambda zips Terraform needs at plan time
98
+ 5. terraform init (initialize providers/modules)
99
+ 6. terraform plan (preview changes)
100
+ 7. Prompt for confirmation (unless --auto)
101
+ 8. terraform apply (deploy changes)
99
102
 
100
103
  Options:
101
104
  --auto, --yes, -y Skip confirmation prompt (auto-approve)
@@ -130,7 +133,8 @@ module Belt
130
133
  belt deploy prod --rebuild # Fast code push to prod
131
134
  belt deploy prod --skip-backup # Skip backups for this deploy
132
135
  belt deploy prod --backup-only # Run backups without deploying
133
- belt deploy frontend dev # Deploy frontend assets only
136
+ belt deploy frontend dev # Deploy frontend asset(s)
137
+ belt deploy frontend dev --frontend ops
134
138
  HELP
135
139
  end
136
140
 
@@ -155,6 +159,7 @@ module Belt
155
159
  warn_active_path_gems!
156
160
  generate_routes_if_needed
157
161
  run_backups unless @skip_backup
162
+ build_zip_artifacts!
158
163
 
159
164
  Dir.chdir(env_dir) do
160
165
  run_init
@@ -663,6 +668,10 @@ module Belt
663
668
  puts ' (timed out waiting, but code was pushed)'
664
669
  end
665
670
 
671
+ def build_zip_artifacts!
672
+ ZipArtifactBuilder.build!(project_root: @project_root, infra_dir: @infra_dir)
673
+ end
674
+
666
675
  def run_init
667
676
  puts '━━━ terraform init ━━━'
668
677
  success = system('terraform', 'init')
@@ -706,15 +715,19 @@ module Belt
706
715
  end
707
716
 
708
717
  def deploy_frontend_if_exists
709
- frontend_dir = File.join(@project_root, 'frontend')
710
- return unless Dir.exist?(frontend_dir) && File.exist?(File.join(frontend_dir, 'package.json'))
711
-
712
- puts "\n━━━ frontend deploy ━━━"
718
+ require_relative 'frontend_registry'
713
719
  require_relative 'frontend_deploy_command'
714
- Belt::CLI::FrontendDeployCommand.new(@env).run
715
- rescue StandardError => e
716
- puts "\n ⚠ Frontend deploy failed: #{e.message}"
717
- puts " Run `belt deploy frontend #{@env}` manually to retry."
720
+
721
+ frontends = FrontendRegistry.new.existing
722
+ return if frontends.empty?
723
+
724
+ frontends.each do |frontend|
725
+ puts "\n━━━ #{frontend.label} deploy ━━━"
726
+ Belt::CLI::FrontendDeployCommand.new(@env, frontend: frontend).run
727
+ rescue StandardError => e
728
+ puts "\n ⚠ #{frontend.label.capitalize} deploy failed: #{e.message}"
729
+ puts " Run `belt deploy frontend #{@env} --frontend #{frontend.name}` manually to retry."
730
+ end
718
731
  end
719
732
 
720
733
  def print_outputs(env_dir)
@@ -3,6 +3,7 @@
3
3
  require 'fileutils'
4
4
  require_relative 'app_detection'
5
5
  require_relative 'auth_command'
6
+ require_relative 'frontend_registry'
6
7
  require_relative 'generator_registry'
7
8
  require_relative 'tables_command'
8
9
  require_relative '../inflector'
@@ -51,25 +52,28 @@ module Belt
51
52
  flags = parse_environment_flags(args)
52
53
  new(generator, name, [], **flags).destroy
53
54
  when 'frontend'
54
- new(generator, nil, []).destroy
55
+ frontend_name = FrontendRegistry.extract_flag!(args, '--frontend')
56
+ new(generator, nil, [], frontend_name: frontend_name).destroy
55
57
  when 'auth'
56
58
  Belt::CLI::AuthCommand.destroy(args)
57
59
  when 'views'
60
+ frontend_name = FrontendRegistry.extract_flag!(args, '--frontend')
58
61
  name = args.shift
59
62
  if name.nil? || name.empty?
60
- puts 'Usage: belt destroy views <name>'
63
+ puts 'Usage: belt destroy views <name> [--frontend NAME]'
61
64
  exit 1
62
65
  end
63
- new(generator, name, args.map { |a| parse_field(a) }).destroy
66
+ new(generator, name, args.map { |a| parse_field(a) }, frontend_name: frontend_name).destroy
64
67
  when 'index'
65
68
  Belt::CLI::IndexCommand.run(['remove'] + args)
66
69
  else
70
+ frontend_name = FrontendRegistry.extract_flag!(args, '--frontend')
67
71
  name = args.shift
68
72
  if name.nil? || name.empty?
69
73
  puts "Usage: belt destroy #{generator} <name>"
70
74
  exit 1
71
75
  end
72
- new(generator, name, args.map { |a| parse_field(a) }).destroy
76
+ new(generator, name, args.map { |a| parse_field(a) }, frontend_name: frontend_name).destroy
73
77
  end
74
78
  end
75
79
 
@@ -105,7 +109,7 @@ module Belt
105
109
  controller Remove a controller
106
110
  auth Remove Cognito user pool infrastructure
107
111
  environment Remove a deployment environment and tear down infrastructure
108
- frontend Remove the frontend/ directory
112
+ frontend Remove a frontend directory (use --frontend NAME when several exist)
109
113
  views Remove React pages for a resource
110
114
 
111
115
  Environment options:
@@ -120,7 +124,9 @@ module Belt
120
124
  belt d environment dev --skip-terraform
121
125
  belt d environment dev --force
122
126
  belt d frontend
127
+ belt d frontend --frontend ops
123
128
  belt d views post
129
+ belt d views post --frontend ops
124
130
 
125
131
  ⚠ This is destructive. Files will be permanently deleted.
126
132
 
@@ -129,12 +135,14 @@ module Belt
129
135
  HELP
130
136
  end
131
137
 
132
- def initialize(generator, name, fields, force: false, skip_terraform: false)
138
+ # rubocop:disable Metrics/ParameterLists -- keyword options for destroy flags
139
+ def initialize(generator, name, fields, force: false, skip_terraform: false, frontend_name: nil)
133
140
  @generator = generator
134
141
  @name = name&.downcase&.gsub(/[^a-z0-9_]/, '_')
135
142
  @fields = fields
136
143
  @force = force
137
144
  @skip_terraform = skip_terraform
145
+ @frontend_name = frontend_name
138
146
  @app_name = detect_namespace
139
147
  @singular_name = @name ? Belt::Inflector.singularize(@name) : nil
140
148
  @resource_name = @singular_name ? Belt::Inflector.pluralize(@singular_name) : nil
@@ -142,6 +150,7 @@ module Belt
142
150
  @removed = []
143
151
  @updated = []
144
152
  end
153
+ # rubocop:enable Metrics/ParameterLists
145
154
 
146
155
  def destroy
147
156
  case @generator
@@ -350,39 +359,62 @@ module Belt
350
359
  end
351
360
 
352
361
  def destroy_frontend
353
- dir = 'frontend'
362
+ frontend = FrontendRegistry.new.resolve!(@frontend_name)
363
+ dir = frontend.path
354
364
  if Dir.exist?(dir)
355
365
  FileUtils.rm_rf(dir)
356
366
  @removed << dir
357
367
  puts " remove #{dir}/"
358
368
 
359
- # Remove frontend.tf from the module
360
- module_frontend = 'infrastructure/modules/app/frontend.tf'
361
- if File.exist?(module_frontend)
362
- FileUtils.rm_f(module_frontend)
363
- @removed << module_frontend
364
- puts " remove #{module_frontend}"
369
+ tf_file = File.join('infrastructure/modules/app', "#{frontend.tf_name}.tf")
370
+ if File.exist?(tf_file)
371
+ FileUtils.rm_f(tf_file)
372
+ @removed << tf_file
373
+ puts " remove #{tf_file}"
365
374
  end
366
375
 
367
- puts "\n✓ Frontend removed!"
376
+ puts "\n✓ #{frontend.label.capitalize} removed!"
368
377
  else
369
- puts '✗ No frontend/ directory found.'
378
+ puts "✗ No #{dir}/ directory found."
370
379
  exit 1
371
380
  end
372
381
  end
373
382
 
383
+ def target_frontends
384
+ registry = FrontendRegistry.new
385
+ return [] if registry.empty?
386
+
387
+ if @frontend_name
388
+ [registry.resolve!(@frontend_name)]
389
+ else
390
+ registry.all
391
+ end
392
+ end
393
+
374
394
  def destroy_views
375
395
  return unless @resource_name
376
396
 
377
- pages_dir = "frontend/src/pages/#{@resource_name}"
378
-
379
- if Dir.exist?(pages_dir)
380
- FileUtils.rm_rf(pages_dir)
381
- @removed << pages_dir
382
- puts " remove #{pages_dir}/"
397
+ targets = target_frontends
398
+ if targets.empty?
399
+ pages_dir = "frontend/src/pages/#{@resource_name}"
400
+ if Dir.exist?(pages_dir)
401
+ FileUtils.rm_rf(pages_dir)
402
+ @removed << pages_dir
403
+ puts " remove #{pages_dir}/"
404
+ end
405
+ remove_view_routes_from('frontend/src/App.jsx')
406
+ return
383
407
  end
384
408
 
385
- remove_view_routes
409
+ targets.each do |frontend|
410
+ pages_dir = "#{frontend.src_dir}/pages/#{@resource_name}"
411
+ if Dir.exist?(pages_dir)
412
+ FileUtils.rm_rf(pages_dir)
413
+ @removed << pages_dir
414
+ puts " remove #{pages_dir}/"
415
+ end
416
+ remove_view_routes_from(frontend.app_jsx)
417
+ end
386
418
  end
387
419
 
388
420
  def remove_file(path)
@@ -467,8 +499,7 @@ module Belt
467
499
  Belt::CLI::TablesCommand.sync_all_environments
468
500
  end
469
501
 
470
- def remove_view_routes
471
- app_jsx = 'frontend/src/App.jsx'
502
+ def remove_view_routes_from(app_jsx)
472
503
  return unless File.exist?(app_jsx)
473
504
 
474
505
  content = File.read(app_jsx)
@@ -3,6 +3,8 @@
3
3
  require 'fileutils'
4
4
  require 'erb'
5
5
  require_relative 'app_detection'
6
+ require_relative 'frontend_registry'
7
+ require_relative 'frontend_setup_command'
6
8
 
7
9
  module Belt
8
10
  module CLI
@@ -52,6 +54,8 @@ module Belt
52
54
  puts " create #{dest_path}" unless @quiet
53
55
  end
54
56
 
57
+ append_extra_frontend_outputs(File.join(dest_dir, 'outputs.tf'))
58
+
55
59
  return if @quiet || !@announce
56
60
 
57
61
  puts "\n✓ Environment '#{@env_name}' created!"
@@ -82,6 +86,14 @@ module Belt
82
86
  File.write(dest_path, content)
83
87
  end
84
88
 
89
+ def append_extra_frontend_outputs(outputs_file)
90
+ FrontendRegistry.new.all.each do |frontend|
91
+ next if frontend.tf_name == 'frontend'
92
+
93
+ FrontendSetupCommand.append_env_outputs_for(frontend, outputs_file)
94
+ end
95
+ end
96
+
85
97
  # Resolve the state bucket name to use in backend.tf.
86
98
  # Priority: existing sibling backend.tf → AWS account ID → bare placeholder.
87
99
  def resolve_state_bucket
@@ -36,7 +36,9 @@ module Belt
36
36
  'backup' => 'backups',
37
37
  'plugin' => 'plugins',
38
38
  'irb' => 'console',
39
- 'repl' => 'console'
39
+ 'repl' => 'console',
40
+ 'frontends' => 'frontend',
41
+ 'spa' => 'frontend'
40
42
  }.freeze
41
43
 
42
44
  def self.run(args)
@@ -5,6 +5,7 @@ require 'erb'
5
5
  require 'json'
6
6
  require 'open3'
7
7
  require_relative 'app_detection'
8
+ require_relative 'frontend_registry'
8
9
 
9
10
  module Belt
10
11
  module CLI
@@ -15,33 +16,39 @@ module Belt
15
16
  include AppDetection
16
17
 
17
18
  def self.run(args)
19
+ name = FrontendRegistry.extract_flag!(args, '--name')
20
+ path = FrontendRegistry.extract_flag!(args, '--path')
18
21
  framework = args.shift
19
22
 
20
23
  if framework.nil? || !FRAMEWORKS.include?(framework)
21
- puts "Usage: belt generate frontend <#{FRAMEWORKS.join('|')}>"
24
+ puts "Usage: belt generate frontend <#{FRAMEWORKS.join('|')}> [--name NAME] [--path DIR]"
22
25
  puts "\nScaffolds a frontend application with build tooling and API client."
23
26
  puts "\nExamples:"
24
27
  puts ' belt generate frontend react'
25
28
  puts ' belt generate frontend vue'
29
+ puts ' belt generate frontend react --name ops --path ops-app'
26
30
  exit 1
27
31
  end
28
32
 
29
- new(framework).generate
33
+ new(framework, name: name, path: path).generate
30
34
  end
31
35
 
32
- def initialize(framework, quiet: false, announce: true)
36
+ def initialize(framework, quiet: false, announce: true, name: nil, path: nil)
33
37
  @framework = framework
34
38
  @quiet = quiet
35
39
  @announce = announce
36
40
  @app_name = detect_app_name
37
41
  @module_name = @app_name.split(/[-_]/).map(&:capitalize).join
42
+ @name = name || (path ? File.basename(path) : 'frontend')
43
+ @path = path || name || 'frontend'
44
+ @frontend = Frontend.new(name: @name, path: @path, default: @name == 'frontend' && @path == 'frontend')
38
45
  end
39
46
 
40
47
  def generate
41
- dest_dir = 'frontend'
48
+ dest_dir = @frontend.path
42
49
 
43
50
  if Dir.exist?(dest_dir) && !Dir.empty?(dest_dir)
44
- puts "Directory 'frontend/' already exists and is not empty."
51
+ puts "Directory '#{dest_dir}/' already exists and is not empty."
45
52
  exit 1
46
53
  end
47
54
 
@@ -54,8 +61,9 @@ module Belt
54
61
  end
55
62
 
56
63
  copy_template(framework_dir, dest_dir)
64
+ register_frontend!
57
65
 
58
- puts "\n✓ Frontend (#{@framework}) created in frontend/" unless @quiet
66
+ puts "\n✓ Frontend (#{@framework}) created in #{dest_dir}/" unless @quiet
59
67
 
60
68
  install_dependencies(dest_dir)
61
69
  setup_frontend_infra_for_existing_environments
@@ -64,7 +72,11 @@ module Belt
64
72
  return if @quiet || !@announce
65
73
 
66
74
  puts "\nNext steps:"
67
- puts ' belt server # Start local dev server'
75
+ if @frontend.name == 'frontend'
76
+ puts ' belt server # Start local dev server'
77
+ else
78
+ puts " belt server --frontend #{@frontend.name}"
79
+ end
68
80
  puts ' belt deploy # Deploy everything to AWS'
69
81
  end
70
82
 
@@ -88,9 +100,18 @@ module Belt
88
100
  end
89
101
  end
90
102
 
103
+ def register_frontend!
104
+ custom = @frontend.name != 'frontend' || @frontend.path != 'frontend'
105
+ config_exists = FrontendRegistry.find_config_path
106
+ return unless custom || config_exists
107
+
108
+ dest = FrontendRegistry.register!(name: @frontend.name, path: @frontend.path)
109
+ puts " update #{dest} (#{@frontend.name})" unless @quiet
110
+ end
111
+
91
112
  def setup_frontend_infra_for_existing_environments
92
113
  module_dir = 'infrastructure/modules/app'
93
- frontend_tf = File.join(module_dir, 'frontend.tf')
114
+ frontend_tf = File.join(module_dir, "#{@frontend.tf_name == 'frontend' ? 'frontend' : @frontend.tf_name}.tf")
94
115
 
95
116
  if File.exist?(frontend_tf)
96
117
  puts " skip #{frontend_tf} (already exists)" unless @quiet
@@ -101,7 +122,7 @@ module Belt
101
122
 
102
123
  puts "\n Setting up frontend infrastructure..." unless @quiet
103
124
  require_relative 'frontend_setup_command'
104
- FrontendSetupCommand.new(nil, quiet: true).run
125
+ FrontendSetupCommand.new(nil, quiet: true, frontend: @frontend).run
105
126
  puts " create #{frontend_tf}" unless @quiet
106
127
  end
107
128
 
@@ -118,7 +139,7 @@ module Belt
118
139
  require_relative 'views_command'
119
140
  resources.each do |resource_name|
120
141
  fields = ViewsCommand.read_schema_fields(resource_name)
121
- ViewsCommand.new(resource_name, fields, force: true).generate
142
+ ViewsCommand.new(resource_name, fields, force: true, frontend: @frontend).generate
122
143
  end
123
144
  end
124
145