belt 0.3.2 → 0.3.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.
Potentially problematic release.
This version of belt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/belt/action_router.rb +13 -2
- data/lib/belt/cli/explain_command.rb +110 -0
- data/lib/belt/cli/routes_command.rb +24 -0
- data/lib/belt/cli.rb +4 -1
- data/lib/belt/docs/backups.md +101 -0
- data/lib/belt/docs/console.md +65 -0
- data/lib/belt/docs/controllers.md +155 -0
- data/lib/belt/docs/deployment.md +141 -0
- data/lib/belt/docs/generators.md +128 -0
- data/lib/belt/docs/lambda_handler.md +105 -0
- data/lib/belt/docs/models.md +160 -0
- data/lib/belt/docs/observability.md +94 -0
- data/lib/belt/docs/plugins.md +94 -0
- data/lib/belt/docs/routing.md +138 -0
- data/lib/belt/docs/structure.md +93 -0
- data/lib/belt/route_dsl.rb +17 -0
- data/lib/belt/version.rb +1 -1
- data/lib/templates/new_app/AGENTS.md.erb +140 -19
- data/lib/templates/new_app/config/routes.rb.erb +5 -2
- metadata +13 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Project Structure
|
|
2
|
+
|
|
3
|
+
A Belt application follows a conventional directory layout. Understanding
|
|
4
|
+
this structure helps you navigate and extend the app effectively.
|
|
5
|
+
|
|
6
|
+
## Standard Layout
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
my-app/
|
|
10
|
+
├── lambda/ # Application code (deployed to Lambda)
|
|
11
|
+
│ ├── api.rb # Lambda entry point
|
|
12
|
+
│ ├── config/
|
|
13
|
+
│ │ └── environment.rb # App boot file (models, libs, AWS setup)
|
|
14
|
+
│ ├── controllers/
|
|
15
|
+
│ │ ├── application_controller.rb
|
|
16
|
+
│ │ └── my_app/ # Namespaced controllers
|
|
17
|
+
│ │ ├── posts_controller.rb
|
|
18
|
+
│ │ └── admin/
|
|
19
|
+
│ │ └── users_controller.rb
|
|
20
|
+
│ ├── models/
|
|
21
|
+
│ │ ├── application_record.rb # Base model class
|
|
22
|
+
│ │ ├── post.rb
|
|
23
|
+
│ │ └── concerns/ # Shared model behavior
|
|
24
|
+
│ ├── lib/
|
|
25
|
+
│ │ └── routes/ # Auto-generated route manifests
|
|
26
|
+
│ │ └── api_routes.rb
|
|
27
|
+
│ └── Gemfile # Lambda-specific dependencies
|
|
28
|
+
├── config/
|
|
29
|
+
│ ├── routes.rb # Route definitions (DSL)
|
|
30
|
+
│ ├── contracts.rb # API request/response contracts
|
|
31
|
+
│ └── lambda/ # Per-lambda configuration
|
|
32
|
+
│ └── api.yml # Timeout, memory, env vars
|
|
33
|
+
├── infrastructure/
|
|
34
|
+
│ ├── modules/ # Shared Terraform modules
|
|
35
|
+
│ │ └── main/
|
|
36
|
+
│ ├── schema.tf.rb # DynamoDB table schema (Ruby DSL)
|
|
37
|
+
│ ├── dev01/ # Per-environment Terraform
|
|
38
|
+
│ │ ├── main.tf
|
|
39
|
+
│ │ ├── variables.tf
|
|
40
|
+
│ │ ├── terraform.tfvars
|
|
41
|
+
│ │ ├── backend.tf
|
|
42
|
+
│ │ └── outputs.tf
|
|
43
|
+
│ └── prod/
|
|
44
|
+
│ └── ...
|
|
45
|
+
├── frontend/ # Optional frontend (React/Vue/Svelte)
|
|
46
|
+
├── Gemfile # Project-level dependencies (CLI, dev tools)
|
|
47
|
+
├── Rakefile # Rake tasks
|
|
48
|
+
├── AGENTS.md # AI agent guide
|
|
49
|
+
└── .gitignore
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Key Files
|
|
53
|
+
|
|
54
|
+
### `lambda/api.rb` — Lambda Entry Point
|
|
55
|
+
|
|
56
|
+
The file AWS Lambda invokes. Includes `Belt::LambdaHandler` and defines `execute`.
|
|
57
|
+
|
|
58
|
+
### `lambda/config/environment.rb` — Boot File
|
|
59
|
+
|
|
60
|
+
Loaded by both Lambda and `belt console`. Sets up AWS clients, requires models,
|
|
61
|
+
configures the app. Everything your app needs to run.
|
|
62
|
+
|
|
63
|
+
### `config/routes.rb` — Route Definitions
|
|
64
|
+
|
|
65
|
+
The Ruby DSL that defines your API. Read by both the Conveyor Belt Terraform
|
|
66
|
+
provider (for infrastructure) and `belt routes` (for manifests).
|
|
67
|
+
|
|
68
|
+
### `config/lambda/api.yml` — Lambda Config
|
|
69
|
+
|
|
70
|
+
Per-function settings: handler path, runtime, timeout, memory, environment
|
|
71
|
+
variables, layers, triggers.
|
|
72
|
+
|
|
73
|
+
### `infrastructure/schema.tf.rb` — Table Schema
|
|
74
|
+
|
|
75
|
+
DynamoDB table definitions in Ruby DSL. Used by `belt setup tables` to generate
|
|
76
|
+
Terraform resources.
|
|
77
|
+
|
|
78
|
+
## Conventions
|
|
79
|
+
|
|
80
|
+
- **Controller namespacing**: Controllers live under `lambda/controllers/<app_name>/`
|
|
81
|
+
to avoid conflicts across modules.
|
|
82
|
+
- **Route manifests**: Generated files in `lambda/lib/routes/` — don't edit manually.
|
|
83
|
+
Regenerate with `belt routes --namespace <name>`.
|
|
84
|
+
- **Two Gemfiles**: Project root Gemfile is for dev tools (belt CLI, rspec).
|
|
85
|
+
`lambda/Gemfile` is what gets packaged into the Lambda.
|
|
86
|
+
- **Config over code**: Lambda configuration (timeout, memory, env vars) goes in
|
|
87
|
+
YAML files, not hardcoded in Terraform.
|
|
88
|
+
|
|
89
|
+
## See Also
|
|
90
|
+
|
|
91
|
+
- `belt explain routing` — how routes.rb maps to infrastructure
|
|
92
|
+
- `belt explain controllers` — controller conventions
|
|
93
|
+
- `belt explain deployment` — how this structure gets deployed
|
data/lib/belt/route_dsl.rb
CHANGED
|
@@ -428,6 +428,23 @@ module Belt
|
|
|
428
428
|
end
|
|
429
429
|
end
|
|
430
430
|
|
|
431
|
+
# Rails-like `root` — defines a GET / route.
|
|
432
|
+
#
|
|
433
|
+
# Examples:
|
|
434
|
+
# root to: "welcome#show"
|
|
435
|
+
# root action: :show, controller: :welcome
|
|
436
|
+
# root "pages#home"
|
|
437
|
+
def root(options_or_target = nil, **options)
|
|
438
|
+
if options_or_target.is_a?(String)
|
|
439
|
+
options[:to] = options_or_target
|
|
440
|
+
elsif options_or_target.is_a?(Hash)
|
|
441
|
+
options = options_or_target.merge(options)
|
|
442
|
+
end
|
|
443
|
+
options[:auth] ||= :none
|
|
444
|
+
route_options = apply_scope_to_route(options)
|
|
445
|
+
@gateway.send(:get, '/', route_options)
|
|
446
|
+
end
|
|
447
|
+
|
|
431
448
|
def resources(name, options = {}, &)
|
|
432
449
|
options = apply_scope_options(options)
|
|
433
450
|
|
data/lib/belt/version.rb
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
This file explains the project structure, tooling, and conventions for AI agents working in this codebase.
|
|
4
4
|
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
belt explain <topic> # Get documentation on any Belt concept
|
|
9
|
+
belt explain routing # How routes work
|
|
10
|
+
belt explain controllers # Controller patterns and response helpers
|
|
11
|
+
belt explain models # ActiveItem (DynamoDB ORM)
|
|
12
|
+
belt explain deployment # Deploy lifecycle
|
|
13
|
+
belt explain generators # Scaffolding new resources
|
|
14
|
+
belt explain --help # List all available topics
|
|
15
|
+
```
|
|
16
|
+
|
|
5
17
|
## Stack
|
|
6
18
|
|
|
7
19
|
- **Belt** — CLI and runtime framework (like Rails for serverless). Provides Lambda handler, action router, controller base class, and CLI tooling.
|
|
@@ -33,6 +45,79 @@ This file explains the project structure, tooling, and conventions for AI agents
|
|
|
33
45
|
└── AGENTS.md # This file
|
|
34
46
|
```
|
|
35
47
|
|
|
48
|
+
## Common Tasks (Copy-Paste Recipes)
|
|
49
|
+
|
|
50
|
+
### Add a new REST resource
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
belt generate resource order item_id:string quantity:number total:number status:string
|
|
54
|
+
belt setup tables <env>
|
|
55
|
+
belt apply <env>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This creates: model, controller (with all CRUD actions), route entry, and DynamoDB schema.
|
|
59
|
+
|
|
60
|
+
### Add a model only (no API endpoint)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
belt generate model audit_log user_id:string action:string resource:string
|
|
64
|
+
belt setup tables <env>
|
|
65
|
+
belt apply <env>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Add a controller only (route already exists)
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
belt generate controller admin/reports
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Add a new route to an existing resource
|
|
75
|
+
|
|
76
|
+
Edit `config/routes.rb`:
|
|
77
|
+
```ruby
|
|
78
|
+
# Inside the gateway block, add:
|
|
79
|
+
get "posts/search", controller: :posts, action: :search
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then add the `search` action to `lambda/controllers/<%= @app_name %>/posts_controller.rb`.
|
|
83
|
+
|
|
84
|
+
### Deploy changes
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
belt deploy <env> # full deploy (init → plan → apply)
|
|
88
|
+
belt deploy <env> --auto # skip confirmation
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Inspect current routes
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
belt routes # human-readable table
|
|
95
|
+
belt routes -f json # machine-readable
|
|
96
|
+
belt routes -g posts # filter by pattern
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Open a console
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
belt c <env> # interactive Ruby session with app loaded
|
|
103
|
+
belt c <env> --run "Post.count" # one-liner
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Check system health
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
belt doctor # verify AWS creds, Terraform, Ruby, etc.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Add a new environment
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
belt generate environment staging
|
|
116
|
+
belt setup state # if no state bucket exists
|
|
117
|
+
belt setup tables staging
|
|
118
|
+
belt deploy staging
|
|
119
|
+
```
|
|
120
|
+
|
|
36
121
|
## Belt CLI Commands
|
|
37
122
|
|
|
38
123
|
```bash
|
|
@@ -43,12 +128,17 @@ belt generate controller <name> # Generate controller onl
|
|
|
43
128
|
belt generate environment <env_name> # Generate Terraform environment directory
|
|
44
129
|
belt setup state # Create/select S3 state bucket
|
|
45
130
|
belt setup tables <env> # Generate DynamoDB table definitions from schema
|
|
131
|
+
belt explain <topic> # Show documentation for a concept
|
|
46
132
|
belt init <env> # terraform init
|
|
47
133
|
belt plan <env> # terraform plan
|
|
48
134
|
belt apply <env> # terraform apply
|
|
49
135
|
belt destroy <env> # terraform destroy
|
|
50
|
-
belt destroy environment <env> # same (mirrors generate environment)
|
|
51
136
|
belt output <env> # terraform output
|
|
137
|
+
belt routes [-g PATTERN] [-f json] # Show route definitions
|
|
138
|
+
belt contracts [-g PATTERN] [-f json] # Show API contracts
|
|
139
|
+
belt console <env> # Interactive Ruby console
|
|
140
|
+
belt logs <lambda> [-f] [-s 5m] [-e env] # View Lambda logs
|
|
141
|
+
belt doctor # Check dependencies
|
|
52
142
|
```
|
|
53
143
|
|
|
54
144
|
## How Routing Works
|
|
@@ -62,12 +152,12 @@ belt output <env> # terraform output
|
|
|
62
152
|
end
|
|
63
153
|
```
|
|
64
154
|
|
|
65
|
-
2. Conveyor Belt creates
|
|
155
|
+
2. Conveyor Belt creates API Gateway routes. URLs look like:
|
|
66
156
|
```
|
|
67
157
|
https://api.<env>.example.com/<%= @app_name %>/things
|
|
68
158
|
```
|
|
69
159
|
|
|
70
|
-
3. The Lambda entry point (`lambda/<%= @app_name %>.rb`) uses `Belt::ActionRouter` to dispatch requests to controllers based on the route manifest
|
|
160
|
+
3. The Lambda entry point (`lambda/<%= @app_name %>.rb`) uses `Belt::ActionRouter` to dispatch requests to controllers based on the route manifest.
|
|
71
161
|
|
|
72
162
|
4. `resources :things` generates: `GET /things`, `POST /things`, `GET /things/:id`, `PUT /things/:id`, `DELETE /things/:id`. **PUT, not PATCH.**
|
|
73
163
|
|
|
@@ -83,7 +173,13 @@ end
|
|
|
83
173
|
|
|
84
174
|
Table names resolve as `{APP_NAME}-{ENVIRONMENT}-{pluralized_model}` (e.g., `<%= @app_name %>-wups-posts`).
|
|
85
175
|
|
|
86
|
-
Key
|
|
176
|
+
Key methods: `create!`, `find`, `find_by`, `where`, `update`, `destroy`, `all`, `count`, `exists?`.
|
|
177
|
+
|
|
178
|
+
Querying with indexes:
|
|
179
|
+
```ruby
|
|
180
|
+
Post.where(user_id: "u-123", index: "UserIndex")
|
|
181
|
+
Post.find_by(status: "active", index: "StatusIndex")
|
|
182
|
+
```
|
|
87
183
|
|
|
88
184
|
## How Controllers Work
|
|
89
185
|
|
|
@@ -93,24 +189,35 @@ Controllers inherit from `BeltController::Base`:
|
|
|
93
189
|
module <%= @module_name %>Controllers
|
|
94
190
|
class ThingsController < ApplicationController
|
|
95
191
|
def index
|
|
96
|
-
|
|
97
|
-
success_response(things: items.map(&:to_h))
|
|
192
|
+
@things = Thing.all # implicit JSON: { "things": [...] }
|
|
98
193
|
end
|
|
99
194
|
|
|
100
195
|
def show
|
|
101
|
-
|
|
102
|
-
success_response(thing: item.to_h)
|
|
196
|
+
@thing = Thing.find(params[:id]) # implicit JSON: { "thing": {...} }
|
|
103
197
|
end
|
|
104
198
|
|
|
105
199
|
def create
|
|
106
|
-
|
|
107
|
-
|
|
200
|
+
attrs = params.require(:thing).permit(:title, :content).to_h
|
|
201
|
+
@thing = Thing.create!(attrs)
|
|
202
|
+
response_status :created # 201 + implicit JSON
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def destroy
|
|
206
|
+
Thing.find(params[:id]).destroy
|
|
207
|
+
head :no_content # 204
|
|
108
208
|
end
|
|
109
209
|
end
|
|
110
210
|
end
|
|
111
211
|
```
|
|
112
212
|
|
|
113
|
-
|
|
213
|
+
**Key patterns:**
|
|
214
|
+
- `params` = merged path parameters + parsed JSON body
|
|
215
|
+
- Instance variables auto-serialize to JSON response
|
|
216
|
+
- `response_status :created` sets status without explicit response
|
|
217
|
+
- `head :no_content` for empty responses
|
|
218
|
+
- `success_response(data, status)` for explicit control
|
|
219
|
+
- `error_response(message, status)` for error responses
|
|
220
|
+
- `rescue_from` for exception handling
|
|
114
221
|
|
|
115
222
|
## Deployment Flow
|
|
116
223
|
|
|
@@ -119,16 +226,30 @@ export AWS_PROFILE=<your_profile>
|
|
|
119
226
|
belt setup state # One-time: create S3 state bucket
|
|
120
227
|
belt generate environment <env> # One-time: scaffold Terraform configs
|
|
121
228
|
belt setup tables <env> # Generate DynamoDB table resources
|
|
122
|
-
belt
|
|
123
|
-
belt apply <env> # Deploy everything
|
|
229
|
+
belt deploy <env> # Deploy everything (init → plan → apply)
|
|
124
230
|
```
|
|
125
231
|
|
|
126
|
-
##
|
|
232
|
+
## Key Differences from Rails
|
|
233
|
+
|
|
234
|
+
| Rails | Belt |
|
|
235
|
+
|-------|------|
|
|
236
|
+
| PostgreSQL / MySQL | DynamoDB (NoSQL) |
|
|
237
|
+
| ActiveRecord | ActiveItem |
|
|
238
|
+
| `PATCH` for updates | `PUT` for updates |
|
|
239
|
+
| `rails server` | Deployed to AWS Lambda |
|
|
240
|
+
| `rails routes` | `belt routes` |
|
|
241
|
+
| `rails console` | `belt console <env>` |
|
|
242
|
+
| `config/routes.rb` → URL paths | `config/routes.rb` → URL paths + infrastructure |
|
|
243
|
+
| Migrations | `belt setup tables <env>` |
|
|
244
|
+
| `has_many` / `belongs_to` | Manual (no joins in DynamoDB) |
|
|
245
|
+
| Template rendering | JSON responses (default) |
|
|
246
|
+
|
|
247
|
+
## Troubleshooting
|
|
127
248
|
|
|
128
249
|
```bash
|
|
129
|
-
belt
|
|
130
|
-
belt
|
|
131
|
-
belt
|
|
250
|
+
belt doctor # Check all dependencies
|
|
251
|
+
belt explain <topic> # Documentation for any concept
|
|
252
|
+
belt routes -f json # Verify route configuration
|
|
253
|
+
belt logs <lambda> -e <env> -s 5m # Check recent Lambda logs
|
|
254
|
+
belt c <env> --run "Post.count" # Verify data access
|
|
132
255
|
```
|
|
133
|
-
|
|
134
|
-
This creates the model, controller, updates routes + schema, generates the DynamoDB table definition, and deploys.
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
Belt.application.routes.draw do
|
|
2
4
|
# Creates an API Gateway named "api" with a default Lambda function of the same name.
|
|
3
5
|
# Use `function :other_name do ... end` inside to route specific paths to additional Lambdas.
|
|
4
6
|
gateway :api do
|
|
5
|
-
# Public stack-check / welcome (HTML for browsers, JSON for the SPA shell)
|
|
6
|
-
|
|
7
|
+
# Public stack-check / welcome (HTML for browsers, JSON for the SPA shell).
|
|
8
|
+
# This route is auto-injected by Belt if omitted, but keeping it explicit is clearer.
|
|
9
|
+
root to: 'welcome#show'
|
|
7
10
|
# resources :posts
|
|
8
11
|
end
|
|
9
12
|
end
|
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.3.
|
|
4
|
+
version: 0.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stowzilla
|
|
@@ -116,6 +116,7 @@ files:
|
|
|
116
116
|
- lib/belt/cli/env_resolver.rb
|
|
117
117
|
- lib/belt/cli/environment_command.rb
|
|
118
118
|
- lib/belt/cli/environment_config.rb
|
|
119
|
+
- lib/belt/cli/explain_command.rb
|
|
119
120
|
- lib/belt/cli/frontend_command.rb
|
|
120
121
|
- lib/belt/cli/frontend_deploy_command.rb
|
|
121
122
|
- lib/belt/cli/frontend_env_command.rb
|
|
@@ -140,6 +141,17 @@ files:
|
|
|
140
141
|
- lib/belt/cli/views_command.rb
|
|
141
142
|
- lib/belt/configuration.rb
|
|
142
143
|
- lib/belt/controllers/welcome_controller.rb
|
|
144
|
+
- lib/belt/docs/backups.md
|
|
145
|
+
- lib/belt/docs/console.md
|
|
146
|
+
- lib/belt/docs/controllers.md
|
|
147
|
+
- lib/belt/docs/deployment.md
|
|
148
|
+
- lib/belt/docs/generators.md
|
|
149
|
+
- lib/belt/docs/lambda_handler.md
|
|
150
|
+
- lib/belt/docs/models.md
|
|
151
|
+
- lib/belt/docs/observability.md
|
|
152
|
+
- lib/belt/docs/plugins.md
|
|
153
|
+
- lib/belt/docs/routing.md
|
|
154
|
+
- lib/belt/docs/structure.md
|
|
143
155
|
- lib/belt/helpers/cors_origin.rb
|
|
144
156
|
- lib/belt/helpers/error_logging.rb
|
|
145
157
|
- lib/belt/helpers/response.rb
|