belt 0.1.3 → 0.1.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.
data/lib/belt/cli.rb CHANGED
@@ -11,6 +11,8 @@ require_relative 'cli/frontend_deploy_command'
11
11
  require_relative 'cli/views_command'
12
12
  require_relative 'cli/setup_command'
13
13
  require_relative 'cli/terraform_command'
14
+ require_relative 'cli/deploy_command'
15
+ require_relative 'cli/server_command'
14
16
  require_relative 'cli/routes_command'
15
17
  require_relative 'cli/tasks_command'
16
18
  require_relative 'cli/console_command'
@@ -24,15 +26,8 @@ module Belt
24
26
  %w[console c] => Belt::CLI::ConsoleCommand,
25
27
  %w[tasks --tasks -T] => Belt::CLI::TasksCommand,
26
28
  'setup' => Belt::CLI::SetupCommand,
27
- 'deploy' => lambda { |args|
28
- subcommand = args.shift
29
- if subcommand == 'frontend'
30
- Belt::CLI::FrontendDeployCommand.run(args)
31
- else
32
- puts 'Usage: belt deploy frontend <environment>'
33
- exit 1
34
- end
35
- },
29
+ 'deploy' => Belt::CLI::DeployCommand,
30
+ %w[server s] => Belt::CLI::ServerCommand,
36
31
  %w[version --version -v] => ->(_args) { puts "Belt #{Belt::VERSION}" }
37
32
  }.freeze
38
33
 
@@ -80,6 +75,10 @@ module Belt
80
75
  generate frontend <react|vue|svelte> Scaffold a frontend app
81
76
  generate views <resource> [fields...] Generate React pages for REST actions
82
77
  generate environment <name> Create a new environment
78
+ server Start local dev server (frontend)
79
+ s Alias for server
80
+ deploy [environment] Deploy to AWS (init → plan → apply)
81
+ deploy frontend <env> Build and deploy frontend to AWS
83
82
  routes [-g PATTERN] [-f json] Show route definitions
84
83
  console Start an interactive console (IRB)
85
84
  c Alias for console
@@ -88,12 +87,11 @@ module Belt
88
87
  setup state Create/select S3 state bucket
89
88
  setup tables <env> Generate DynamoDB tables from schema
90
89
  setup frontend <env> Generate S3 + CloudFront infrastructure
91
- deploy frontend <env> Build and deploy frontend to AWS
92
- init <env> terraform init for environment
93
- plan <env> terraform plan for environment
94
- apply <env> terraform apply for environment
95
- destroy <env> terraform destroy for environment
96
- output <env> terraform output for environment
90
+ init [environment] <env> terraform init for environment
91
+ plan [environment] <env> terraform plan for environment
92
+ apply [environment] <env> terraform apply for environment
93
+ destroy [environment] <env> terraform destroy for environment
94
+ output [environment] <env> terraform output for environment
97
95
  --version Show Belt version
98
96
 
99
97
  Rake Tasks:
@@ -110,8 +108,11 @@ module Belt
110
108
  belt new blog --frontend react
111
109
  belt generate resource post title:string content:text status:string
112
110
  belt generate frontend react
113
- belt setup frontend wups
111
+ belt server # Start local frontend server
112
+ belt deploy # Deploy dev to AWS
113
+ belt deploy prod --auto # Deploy prod without confirmation
114
114
  belt deploy frontend wups
115
+ belt setup frontend wups
115
116
  belt apply wups
116
117
  belt tasks # list all rake tasks
117
118
  belt lambda:build_layer # run a rake task directly
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module Belt
6
+ # Gem-embedded welcome controller that serves the default "it works!" page.
7
+ # Resolved via the ActionRouter's Belt:: namespace fallback when no app-defined
8
+ # WelcomeController exists. Gets replaced once the user defines their own root route.
9
+ class WelcomeController < BeltController::Base
10
+ skip_before_action :authenticate!
11
+
12
+ ASSETS_DIR = File.expand_path('../assets', __dir__)
13
+
14
+ def show
15
+ title = ENV.fetch('WELCOME_TITLE', 'Welcome to Belt')
16
+ subtitle = ENV.fetch('WELCOME_SUBTITLE', 'API Gateway → Lambda → DynamoDB — all connected.')
17
+ app_name = ENV.fetch('APP_NAME', 'my-app')
18
+
19
+ html_response(render_welcome_page(title: title, subtitle: subtitle, app_name: app_name))
20
+ end
21
+
22
+ private
23
+
24
+ def render_welcome_page(title:, subtitle:, app_name:)
25
+ <<~HTML
26
+ <!DOCTYPE html>
27
+ <html lang="en">
28
+ <head>
29
+ <meta charset="UTF-8">
30
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
31
+ <title>#{escape_html(title)}</title>
32
+ <style>#{welcome_css}</style>
33
+ </head>
34
+ <body>
35
+ <div class="hero">
36
+ <img src="data:image/png;base64,#{background_image_base64}" alt="Belt" class="hero-bg" />
37
+ <div class="overlay">
38
+ <h1>#{escape_html(title)}</h1>
39
+ <p class="subtitle">#{escape_html(subtitle)}</p>
40
+ </div>
41
+ </div>
42
+ <div class="container">
43
+ <div class="stack-check">
44
+ <div class="check-item check-pass">
45
+ <span class="icon">✓</span>
46
+ <span>API Gateway</span>
47
+ </div>
48
+ <div class="arrow">→</div>
49
+ <div class="check-item check-pass">
50
+ <span class="icon">✓</span>
51
+ <span>Lambda</span>
52
+ </div>
53
+ <div class="arrow">→</div>
54
+ #{dynamodb_check_html}
55
+ </div>
56
+ <div class="next-steps">
57
+ <h2>Next Steps</h2>
58
+ <ol>
59
+ <li>Generate a resource: <code>belt g resource post title:string body:text</code></li>
60
+ <li>Deploy: <code>belt deploy</code></li>
61
+ <li>This page will be replaced once you define your own root route.</li>
62
+ </ol>
63
+ </div>
64
+ </div>
65
+ </body>
66
+ </html>
67
+ HTML
68
+ end
69
+
70
+ def dynamodb_check_html
71
+ if dynamodb_connected?
72
+ '<div class="check-item check-pass"><span class="icon">✓</span><span>DynamoDB</span></div>'
73
+ else
74
+ '<div class="check-item check-warn"><span class="icon">⚠</span><span>DynamoDB</span></div>'
75
+ end
76
+ end
77
+
78
+ def dynamodb_connected?
79
+ return false unless defined?(Aws::DynamoDB::Client)
80
+
81
+ client = Aws::DynamoDB::Client.new
82
+ client.list_tables(limit: 1)
83
+ true
84
+ rescue StandardError
85
+ false
86
+ end
87
+
88
+ def escape_html(text)
89
+ text.to_s.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;').gsub('"', '&quot;')
90
+ end
91
+
92
+ def welcome_css
93
+ @welcome_css ||= File.read(File.join(ASSETS_DIR, 'welcome.css'))
94
+ end
95
+
96
+ def background_image_base64
97
+ @background_image_base64 ||= Base64.strict_encode64(
98
+ File.binread(File.join(ASSETS_DIR, 'belt-default.png'))
99
+ )
100
+ end
101
+ end
102
+ end
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.3'
4
+ VERSION = '0.1.5'
5
5
  end
data/lib/belt.rb CHANGED
@@ -55,3 +55,4 @@ module Belt
55
55
  end
56
56
 
57
57
  require_relative 'belt_controller/base'
58
+ require_relative 'belt/controllers/welcome_controller'
@@ -1,6 +1,6 @@
1
1
  terraform {
2
2
  backend "s3" {
3
- bucket = "<%= @app_name %>-terraform-state"
3
+ bucket = "<%= s3_safe_name(@app_name) %>-terraform-state"
4
4
  key = "<%= @env_name %>/terraform.tfstate"
5
5
  region = "us-east-1"
6
6
  encrypt = true
@@ -8,9 +8,9 @@ terraform {
8
8
  source = "hashicorp/random"
9
9
  version = "~> 3.0"
10
10
  }
11
- dispatcher = {
12
- source = "terraform.local/stowzilla/dispatcher"
13
- version = "99.0.0"
11
+ conveyor-belt = {
12
+ source = "stowzilla/conveyor-belt"
13
+ version = "~> 0.0.1"
14
14
  }
15
15
  }
16
16
  }
@@ -27,12 +27,13 @@ provider "aws" {
27
27
  }
28
28
  }
29
29
 
30
- provider "dispatcher" {
30
+ provider "conveyor-belt" {
31
31
  environment = var.environment
32
32
  aws_region = var.aws_region
33
33
  }
34
34
 
35
- resource "dispatcher" "main" {
35
+ resource "conveyor_belt" "main" {
36
+ provider = conveyor-belt
36
37
  source = "${path.module}/../routes.tf.rb"
37
38
  app_name = var.app_name
38
39
  lambda_source_dir = "${path.module}/../../lambda"
@@ -0,0 +1,9 @@
1
+ output "api_url" {
2
+ description = "API Gateway base URL"
3
+ value = conveyor_belt.main.api_gateway_urls
4
+ }
5
+
6
+ output "lambda_functions" {
7
+ description = "Map of action names to Lambda function ARNs"
8
+ value = conveyor_belt.main.lambda_functions
9
+ }
@@ -9,7 +9,7 @@ resource "random_string" "frontend_suffix" {
9
9
 
10
10
  # S3 bucket for frontend static assets
11
11
  resource "aws_s3_bucket" "frontend" {
12
- bucket = "<%= @app_name %>-frontend-${var.environment}-${random_string.frontend_suffix.result}"
12
+ bucket = "<%= s3_safe_name(@app_name) %>-frontend-${var.environment}-${random_string.frontend_suffix.result}"
13
13
 
14
14
  lifecycle {
15
15
  ignore_changes = [bucket]
@@ -155,5 +155,5 @@ output "frontend_url" {
155
155
  }
156
156
 
157
157
  output "api_url" {
158
- value = values(dispatcher.main.api_gateway_urls)[0]
158
+ value = values(conveyor_belt.main.api_gateway_urls)[0]
159
159
  }
@@ -6,7 +6,7 @@ This file explains the project structure, tooling, and conventions for AI agents
6
6
 
7
7
  - **Belt** — CLI and runtime framework (like Rails for serverless). Provides Lambda handler, action router, controller base class, and CLI tooling.
8
8
  - **ActiveItem** — ActiveRecord-like ORM for DynamoDB. Models inherit from `ActiveItem::Base`.
9
- - **Dispatcher** — Terraform provider that reads a Ruby DSL (`routes.tf.rb`) and creates API Gateway + Lambda + IAM infrastructure.
9
+ - **Conveyor Belt** — Terraform provider that reads a Ruby DSL (`routes.tf.rb`) and creates API Gateway + Lambda + IAM infrastructure.
10
10
  - **Lambda Loadout** — Lambda cold-start optimizer (auto-required by Belt).
11
11
 
12
12
  ## Project Structure
@@ -23,7 +23,7 @@ This file explains the project structure, tooling, and conventions for AI agents
23
23
  │ ├── lib/routes/ # Route manifests (auto-generated)
24
24
  │ └── Gemfile # Lambda-specific dependencies
25
25
  ├── infrastructure/
26
- │ ├── routes.tf.rb # API routes (Dispatcher DSL)
26
+ │ ├── routes.tf.rb # API routes (Conveyor Belt DSL)
27
27
  │ ├── schema.tf.rb # Model schema definitions
28
28
  │ └── <env>/ # Per-environment Terraform configs
29
29
  ├── Gemfile # Project-level dependencies
@@ -44,6 +44,7 @@ belt init <env> # terraform init
44
44
  belt plan <env> # terraform plan
45
45
  belt apply <env> # terraform apply
46
46
  belt destroy <env> # terraform destroy
47
+ belt destroy environment <env> # same (mirrors generate environment)
47
48
  belt output <env> # terraform output
48
49
  ```
49
50
 
@@ -58,7 +59,7 @@ belt output <env> # terraform output
58
59
  end
59
60
  ```
60
61
 
61
- 2. Dispatcher creates an API Gateway where the namespace becomes a base path mapping. URLs look like:
62
+ 2. Conveyor Belt creates an API Gateway where the namespace becomes a base path mapping. URLs look like:
62
63
  ```
63
64
  https://api.<env>.example.com/<%= @app_name %>/things
64
65
  ```
@@ -1,5 +1,6 @@
1
1
  Belt.application.routes.draw do
2
2
  namespace :<%= @app_name %> do
3
+ get "/", action: :show, controller: :welcome
3
4
  # resources :posts
4
5
  end
5
6
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Routes
4
4
  <%= @module_name.upcase %> = [
5
+ { verb: 'GET', path: '/', controller: 'welcome', action: 'show' },
5
6
  # { verb: 'GET', path: '/posts', controller: 'posts', action: 'index' },
6
7
  # { verb: 'POST', path: '/posts', controller: 'posts', action: 'create' },
7
8
  # { verb: 'GET', path: '/posts/{id}', controller: 'posts', action: 'show' },
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.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stowzilla
@@ -52,10 +52,13 @@ files:
52
52
  - exe/belt
53
53
  - lib/belt.rb
54
54
  - lib/belt/action_router.rb
55
+ - lib/belt/assets/belt-default.png
56
+ - lib/belt/assets/welcome.css
55
57
  - lib/belt/cli.rb
56
58
  - lib/belt/cli/app_detection.rb
57
59
  - lib/belt/cli/bucket_security.rb
58
60
  - lib/belt/cli/console_command.rb
61
+ - lib/belt/cli/deploy_command.rb
59
62
  - lib/belt/cli/env_resolver.rb
60
63
  - lib/belt/cli/environment_command.rb
61
64
  - lib/belt/cli/frontend_command.rb
@@ -66,11 +69,13 @@ files:
66
69
  - lib/belt/cli/routes_command.rb
67
70
  - lib/belt/cli/routes_command/route_inference.rb
68
71
  - lib/belt/cli/routes_command/schema_loader.rb
72
+ - lib/belt/cli/server_command.rb
69
73
  - lib/belt/cli/setup_command.rb
70
74
  - lib/belt/cli/tables_command.rb
71
75
  - lib/belt/cli/tasks_command.rb
72
76
  - lib/belt/cli/terraform_command.rb
73
77
  - lib/belt/cli/views_command.rb
78
+ - lib/belt/controllers/welcome_controller.rb
74
79
  - lib/belt/helpers/cors_origin.rb
75
80
  - lib/belt/helpers/error_logging.rb
76
81
  - lib/belt/helpers/response.rb
@@ -84,6 +89,7 @@ files:
84
89
  - lib/belt_controller/base.rb
85
90
  - lib/templates/environment/backend.tf.erb
86
91
  - lib/templates/environment/main.tf.erb
92
+ - lib/templates/environment/outputs.tf.erb
87
93
  - lib/templates/environment/terraform.tfvars.erb
88
94
  - lib/templates/environment/variables.tf.erb
89
95
  - lib/templates/frontend/react/index.html.erb