Skip to content

Commit eb42870

Browse files
committed
Add WebSocket, template, and CLI support to RustAPI
Introduces new crates: rustapi-ws for WebSocket support, rustapi-view for Tera-based template rendering, and cargo-rustapi as a CLI tool for project scaffolding and utilities. Updates workspace and dependencies in Cargo.toml, expands documentation in README.md to cover new features, and adds example projects for WebSocket and template usage. Also includes new modules and features in rustapi-core and rustapi-extras to support these capabilities.
1 parent 44f820a commit eb42870

65 files changed

Lines changed: 10674 additions & 36 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 683 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ members = [
88
"crates/rustapi-openapi",
99
"crates/rustapi-extras",
1010
"crates/rustapi-toon",
11+
"crates/rustapi-ws",
12+
"crates/rustapi-view",
13+
"crates/cargo-rustapi",
1114
"examples/hello-world",
1215
"examples/sqlx-crud",
1316
"examples/crud-api",
1417
"examples/auth-api",
1518
"examples/proof-of-concept",
1619
"examples/toon-api",
1720
"examples/mcp-server",
21+
"examples/websocket",
22+
"examples/templates",
1823
"benches/toon_bench",
1924
]
2025

@@ -83,10 +88,26 @@ toon-format = { version = "0.4", default-features = false }
8388
# Benchmarking
8489
criterion = { version = "0.5", features = ["html_reports"] }
8590

91+
# WebSocket
92+
tokio-tungstenite = "0.24"
93+
tungstenite = "0.24"
94+
95+
# Template engine
96+
tera = "1.19"
97+
98+
# CLI
99+
clap = { version = "4.5", features = ["derive", "color"] }
100+
dialoguer = "0.11"
101+
indicatif = "0.17"
102+
console = "0.15"
103+
86104
# Internal crates
87105
rustapi-core = { path = "crates/rustapi-core", version = "0.1.4", default-features = false }
88106
rustapi-macros = { path = "crates/rustapi-macros", version = "0.1.4" }
89107
rustapi-validate = { path = "crates/rustapi-validate", version = "0.1.4" }
90108
rustapi-openapi = { path = "crates/rustapi-openapi", version = "0.1.4", default-features = false }
91109
rustapi-extras = { path = "crates/rustapi-extras", version = "0.1.4" }
92110
rustapi-toon = { path = "crates/rustapi-toon", version = "0.1.4" }
111+
rustapi-ws = { path = "crates/rustapi-ws", version = "0.1.4" }
112+
rustapi-view = { path = "crates/rustapi-view", version = "0.1.4" }
113+

README.md

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,24 +112,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
112112

113113
| Feature | Description |
114114
|---------|-------------|
115-
| **Type-Safe Extractors** | `Json<T>`, `Query<T>`, `Path<T>` — compile-time guarantees |
115+
| **Type-Safe Extractors** | `Json<T>`, `Query<T>`, `Path<T>`, `WebSocket` — compile-time guarantees |
116116
| **Zero-Config Routing** | Macro-decorated routes auto-register at startup (`RustApi::auto()`) |
117117
| **Auto OpenAPI** | Your code = your docs. `/docs` endpoint out of the box |
118118
| **Validation** | `#[validate(email)]` → automatic 422 responses |
119119
| **JWT Auth** | One-line auth with `AuthUser<T>` extractor |
120120
| **CORS & Rate Limit** | Production-ready middleware |
121121
| **TOON Format** | **50-58% token savings** for LLMs |
122+
| **WebSocket** | Real-time bidirectional communication with broadcast support |
123+
| **Template Engine** | Server-side HTML rendering with Tera templates |
124+
| **CLI Tool** | `cargo-rustapi` for project scaffolding |
122125

123126
### Optional Features
124127

125128
```toml
126-
rustapi-rs = { version = "0.1.4", features = ["jwt", "cors", "toon"] }
129+
rustapi-rs = { version = "0.1.4", features = ["jwt", "cors", "toon", "ws", "view"] }
127130
```
128131

129132
- `jwt` — JWT authentication
130133
- `cors` — CORS middleware
131134
- `rate-limit` — IP-based rate limiting
132135
- `toon` — LLM-optimized responses
136+
- `ws` — WebSocket support
137+
- `view` — Template engine (Tera)
133138
- `full` — Everything included
134139

135140
---
@@ -145,10 +150,73 @@ cargo run -p auth-api
145150
cargo run -p sqlx-crud
146151
cargo run -p toon-api
147152
cargo run -p proof-of-concept
153+
cargo run -p websocket # WebSocket example
154+
cargo run -p templates # Template engine example
148155
```
149156

150157
---
151158

159+
## 🔌 Real-time: WebSocket Support
160+
161+
RustAPI provides first-class WebSocket support for real-time applications.
162+
163+
```rust
164+
use rustapi_rs::ws::{WebSocket, Message, Broadcast};
165+
166+
#[rustapi_rs::get("/ws")]
167+
async fn websocket(ws: WebSocket) -> WebSocketUpgrade {
168+
ws.on_upgrade(handle_connection)
169+
}
170+
171+
async fn handle_connection(mut stream: WebSocketStream) {
172+
while let Some(msg) = stream.recv().await {
173+
match msg {
174+
Message::Text(text) => {
175+
stream.send(Message::Text(format!("Echo: {}", text))).await.ok();
176+
}
177+
Message::Close(_) => break,
178+
_ => {}
179+
}
180+
}
181+
}
182+
```
183+
184+
**Features:**
185+
- Full WebSocket protocol support (text, binary, ping/pong)
186+
- `Broadcast` channel for pub/sub patterns
187+
- Seamless integration with RustAPI routing
188+
189+
---
190+
191+
## 🎨 Template Engine
192+
193+
Server-side HTML rendering with Tera templates.
194+
195+
```rust
196+
use rustapi_rs::view::{Templates, View, ContextBuilder};
197+
198+
#[rustapi_rs::get("/")]
199+
async fn home(templates: Templates) -> View<()> {
200+
View::new(&templates, "index.html", ())
201+
}
202+
203+
#[rustapi_rs::get("/users/{id}")]
204+
async fn user_page(templates: Templates, Path(id): Path<u64>) -> View<User> {
205+
let user = get_user(id);
206+
View::with_context(&templates, "user.html", user, |ctx| {
207+
ctx.insert("title", &format!("User: {}", user.name));
208+
})
209+
}
210+
```
211+
212+
**Features:**
213+
- Tera template engine (Jinja2-like syntax)
214+
- Type-safe context with `ContextBuilder`
215+
- Template inheritance support
216+
- Auto-escape HTML by default
217+
218+
---
219+
152220
## 🤖 LLM-Optimized: TOON Format
153221

154222
RustAPI is built for **AI-powered APIs**.
@@ -179,6 +247,34 @@ async fn users(accept: AcceptHeader) -> LlmResponse<UsersResponse> {
179247

180248
---
181249

250+
## 🛠️ CLI Tool: cargo-rustapi
251+
252+
Scaffold new RustAPI projects with ease.
253+
254+
```bash
255+
# Install the CLI
256+
cargo install cargo-rustapi
257+
258+
# Create a new project
259+
cargo rustapi new my-api
260+
261+
# Interactive mode
262+
cargo rustapi new my-api --interactive
263+
```
264+
265+
**Available Templates:**
266+
- `minimal` — Basic RustAPI setup
267+
- `api` — REST API with CRUD operations
268+
- `web` — Full web app with templates and WebSocket
269+
- `full` — Everything included
270+
271+
**Commands:**
272+
- `cargo rustapi new <name>` — Create new project
273+
- `cargo rustapi generate <type>` — Generate handlers, models, middleware
274+
- `cargo rustapi docs` — Generate API documentation
275+
276+
---
277+
182278
## Architecture
183279

184280
RustAPI follows a **Facade Architecture** — a stable public API that shields you from internal changes.
@@ -214,6 +310,8 @@ graph TB
214310
Validate["rustapi-validate<br>Request Validation"]
215311
Toon["rustapi-toon<br>LLM Optimization"]
216312
Extras["rustapi-extras<br>JWT/CORS/RateLimit"]
313+
WsCrate["rustapi-ws<br>WebSocket Support"]
314+
ViewCrate["rustapi-view<br>Template Engine"]
217315
end
218316
219317
subgraph Foundation["🏗️ Foundation Layer"]
@@ -292,6 +390,8 @@ graph BT
292390
Validate[rustapi-validate]
293391
Toon[rustapi-toon]
294392
Extras[rustapi-extras]
393+
WS[rustapi-ws]
394+
View[rustapi-view]
295395
end
296396
297397
subgraph External["External Dependencies"]
@@ -300,6 +400,8 @@ graph BT
300400
Serde[serde]
301401
Utoipa[utoipa]
302402
Validator[validator]
403+
Tungstenite[tungstenite]
404+
Tera[tera]
303405
end
304406
305407
App --> RS
@@ -309,13 +411,17 @@ graph BT
309411
RS --> Validate
310412
RS -.->|optional| Toon
311413
RS -.->|optional| Extras
414+
RS -.->|optional| WS
415+
RS -.->|optional| View
312416
313417
Core --> Tokio
314418
Core --> Hyper
315419
Core --> Serde
316420
OpenAPI --> Utoipa
317421
Validate --> Validator
318422
Toon --> Serde
423+
WS --> Tungstenite
424+
View --> Tera
319425
320426
style RS fill:#e1f5fe
321427
style App fill:#c8e6c9
@@ -342,6 +448,8 @@ graph BT
342448
| `rustapi-validate` | Request body/query validation via `#[validate]` |
343449
| `rustapi-toon` | TOON format serializer, content negotiation, LLM headers |
344450
| `rustapi-extras` | JWT auth, CORS, rate limiting middleware |
451+
| `rustapi-ws` | WebSocket support with broadcast channels |
452+
| `rustapi-view` | Template engine (Tera) for server-side rendering |
345453

346454
---
347455

@@ -351,6 +459,9 @@ graph BT
351459
- [x] OpenAPI & Validation
352460
- [x] JWT, CORS, Rate Limiting
353461
- [x] TOON format & LLM optimization
462+
- [x] WebSocket support
463+
- [x] Template engine (Tera)
464+
- [x] CLI tool (cargo-rustapi)
354465
- [ ] *Coming soon...*
355466

356467
---

crates/cargo-rustapi/Cargo.toml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
[package]
2+
name = "cargo-rustapi"
3+
description = "CLI tool for RustAPI - Project scaffolding and development utilities"
4+
version.workspace = true
5+
edition.workspace = true
6+
authors.workspace = true
7+
license.workspace = true
8+
repository.workspace = true
9+
keywords = ["web", "framework", "api", "cli", "scaffold"]
10+
categories = ["command-line-utilities", "development-tools"]
11+
rust-version.workspace = true
12+
readme = "README.md"
13+
14+
[[bin]]
15+
name = "cargo-rustapi"
16+
path = "src/main.rs"
17+
18+
[dependencies]
19+
# CLI
20+
clap = { workspace = true }
21+
dialoguer = { workspace = true }
22+
indicatif = { workspace = true }
23+
console = { workspace = true }
24+
25+
# File system
26+
walkdir = "2.5"
27+
toml_edit = "0.22"
28+
29+
# Async
30+
tokio = { workspace = true, features = ["process", "fs"] }
31+
32+
# Serialization
33+
serde = { workspace = true }
34+
serde_json = { workspace = true }
35+
toml = "0.8"
36+
37+
# Utilities
38+
thiserror = { workspace = true }
39+
tracing = { workspace = true }
40+
tracing-subscriber = { workspace = true }
41+
anyhow = "1.0"
42+
43+
[dev-dependencies]
44+
tempfile = "3.10"
45+
assert_cmd = "2.0"

0 commit comments

Comments
 (0)