diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..efe6d91 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,106 @@ +--- +name: vespera-api-development +description: Guide for developing fully automated OpenAPI/Axum APIs using the Vespera framework. +--- + +# Vespera API Development + +Vespera is a fully automated OpenAPI engine for Axum with zero-config route and schema discovery. +It allows you to write Axum APIs and automatically generate OpenAPI 3.1 specifications. + +## Instructions + +### 1. Project Setup +Add `vespera` to your dependencies: +```toml +[dependencies] +vespera = "0.1.0" +axum = "0.8" +tokio = { version = "1", features = ["full"] } +serde = { version = "1", features = ["derive"] } +``` + +### 2. Main Application +Use the `vespera!` macro in `main.rs` to initialize the app. This macro automatically scans your routes. + +```rust +use vespera::vespera; + +#[tokio::main] +async fn main() { + // Basic initialization + let app = vespera!( + openapi = "openapi.json", // Optional: Generate OpenAPI spec + title = "My API", // Optional: API Title + version = "1.0.0", // Optional: API Version + docs_url = "/docs" // Optional: Serve Swagger UI + ); + + let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); + axum::serve(listener, app).await.unwrap(); +} +``` + +### 3. Route Handlers +Define routes in modules (e.g., `src/routes/`). Use the `#[vespera::route]` attribute. + +```rust +use axum::{Json, Path, State}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct User { + pub id: u32, + pub name: String, +} + +// GET /users/{id} +#[vespera::route(path = "/{id}")] // Defaults to GET if not specified +pub async fn get_user(Path(id): Path) -> Json { + Json(User { id, name: "Alice".into() }) +} + +// POST /users +#[vespera::route(post)] +pub async fn create_user(Json(user): Json) -> Json { + Json(user) +} +``` + +### 5. Error Handling +Vespera supports `Result` return types. It automatically documents both the success capability (200 OK) and the error responses in the OpenAPI spec. + +```rust +use axum::http::StatusCode; + +#[derive(Serialize, Deserialize, Schema)] +pub struct ErrorResponse { + pub message: String, +} + +// Result, Json> +#[vespera::route(get, path = "/may-fail")] +pub async fn may_fail() -> Result, Json> { + Err(Json(ErrorResponse { message: "Something went wrong".to_string() })) +} + +// Result, (StatusCode, Json)> +#[vespera::route(get, path = "/not-found")] +pub async fn not_found_example() -> Result, (StatusCode, Json)> { + Err(( + StatusCode::NOT_FOUND, + Json(ErrorResponse { message: "User not found".to_string() }) + )) +} +``` + +### 4. File Structure +The file structure in `src/routes` maps to URL paths: +- `src/routes/users.rs` -> `/users` +- `src/routes/admin/stats.rs` -> `/admin/stats` + +## Guidelines +- Always use `vespera!` macro instead of manually building `Router::new()`. +- Use `#[vespera::route]` for all handlers to ensure they are picked up by the OpenAPI generator. +- `dir` parameter in `vespera!` defaults to `"routes"`. +- Handlers and schemas are automatically imported.