vespera
11
总安装量
5
周安装量
#27295
全站排名
安装命令
npx skills add https://github.com/dev-five-git/vespera --skill vespera
Agent 安装分布
claude-code
4
windsurf
3
trae
3
opencode
3
cursor
2
Skill 文档
Vespera Usage Guide
Vespera = FastAPI DX for Rust. Zero-config OpenAPI 3.1 generation via compile-time macro scanning.
Quick Start
// 1. Main entry - vespera! macro handles everything
let app = vespera!(
openapi = "openapi.json", // writes file at compile time
title = "My API",
version = "1.0.0",
docs_url = "/docs", // Swagger UI
redoc_url = "/redoc" // ReDoc alternative
);
// 2. Route handlers - MUST be pub async fn
#[vespera::route(get, path = "/{id}", tags = ["users"])]
pub async fn get_user(Path(id): Path<u32>) -> Json<User> { ... }
// 3. Custom types - derive Schema for OpenAPI inclusion
#[derive(Serialize, Deserialize, vespera::Schema)]
pub struct User { id: u32, name: String }
Type Mapping Reference
| Rust Type | OpenAPI Schema | Notes |
|---|---|---|
String, &str |
string |
|
i8–i128, u8–u128 |
integer |
|
f32, f64 |
number |
|
bool |
boolean |
|
Vec<T> |
array + items |
|
Option<T> |
T (nullable context) | Parent marks as optional |
HashMap<K,V> |
object + additionalProperties |
|
() |
empty response | 204 No Content |
| Custom struct | $ref |
Must derive Schema |
Extractor Mapping Reference
| Axum Extractor | OpenAPI Location | Notes |
|---|---|---|
Path<T> |
path parameter | T can be tuple or struct |
Query<T> |
query parameters | Struct fields become params |
Json<T> |
requestBody | application/json |
Form<T> |
requestBody | application/x-www-form-urlencoded |
State<T> |
ignored | Internal, not API |
Extension<T> |
ignored | Internal, not API |
TypedHeader<T> |
header parameter | |
HeaderMap |
ignored | Too dynamic |
Route Handler Requirements
// â Private function - NOT discovered
async fn get_users() -> Json<Vec<User>> { ... }
// â Non-async function - NOT supported
pub fn get_users() -> Json<Vec<User>> { ... }
// â
Must be pub async fn
pub async fn get_users() -> Json<Vec<User>> { ... }
File Structure â URL Mapping
src/routes/
âââ mod.rs â / (root routes)
âââ users.rs â /users
âââ posts.rs â /posts
âââ admin/
âââ mod.rs â /admin
âââ stats.rs â /admin/stats
Handler path is: {file_path} + {#[route] path}
// In src/routes/users.rs
#[vespera::route(get, path = "/{id}")]
pub async fn get_user(...) // â GET /users/{id}
Serde Integration
Vespera respects serde attributes:
#[derive(Serialize, Deserialize, Schema)]
#[serde(rename_all = "camelCase")] // â
Respected in schema
pub struct UserResponse {
user_id: u32, // â "userId" in JSON Schema
#[serde(rename = "fullName")] // â
Respected
name: String, // â "fullName" in JSON Schema
#[serde(default)] // â
Marks as optional in schema
bio: Option<String>,
#[serde(skip)] // â
Excluded from schema
internal_id: u64,
}
Debugging Tips
Schema Not Appearing
- Check
#[derive(Schema)]on the type - Check type is used in a route handler’s input/output
- Check for generic types – all type params need Schema
// Generic types need Schema on all params
#[derive(Schema)]
struct Paginated<T: Schema> { // T must also derive Schema
items: Vec<T>,
total: u32,
}
Macro Expansion
# See what vespera! generates
cargo expand
# Validate OpenAPI output
npx @apidevtools/swagger-cli validate openapi.json
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
VESPERA_DIR |
Route folder name | routes |
VESPERA_OPENAPI |
OpenAPI output path | none |
VESPERA_TITLE |
API title | API |
VESPERA_VERSION |
API version | CARGO_PKG_VERSION |
VESPERA_DOCS_URL |
Swagger UI path | none |
VESPERA_REDOC_URL |
ReDoc path | none |
VESPERA_SERVER_URL |
Server URL | http://localhost:3000 |
Merging Multiple Vespera Apps
Combine routes and OpenAPI specs from multiple apps at compile time.
export_app! Macro
Export an app for merging:
// Child crate (e.g., third/src/lib.rs)
mod routes;
// Basic - scans "routes" folder by default
vespera::export_app!(ThirdApp);
// Custom directory
vespera::export_app!(ThirdApp, dir = "api");
Generates:
ThirdApp::OPENAPI_SPEC: &'static str– OpenAPI JSONThirdApp::router() -> Router– Axum router
merge Parameter
Merge child apps in parent:
let app = vespera!(
openapi = "openapi.json",
docs_url = "/docs",
merge = [third::ThirdApp, other::OtherApp]
)
.with_state(state);
What happens:
- Child routers merged into parent router
- OpenAPI specs merged (paths, schemas, tags)
- Swagger UI shows all routes
How It Works (Compile-Time)
Child compilation (export_app!):
1. Scan routes/ folder
2. Generate OpenAPI spec
3. Write to target/vespera/{Name}.openapi.json
Parent compilation (vespera! with merge):
1. Generate parent OpenAPI spec
2. Read child specs from target/vespera/
3. Merge all specs together
4. Write merged openapi.json