vespera 0.1.13

A fully automated OpenAPI engine for Axum with zero-config route and schema discovery
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# Vespera
A fully automated OpenAPI engine for Axum with zero-config route and schema discovery.

[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/dev-five-git/vespera/CI.yml?branch=main&label=CI)](https://github.com/dev-five-git/vespera/actions)
[![Codecov](https://img.shields.io/codecov/c/github/dev-five-git/vespera)](https://codecov.io/gh/dev-five-git/vespera)
[![GitHub stars](https://img.shields.io/github/stars/dev-five-git/vespera.svg?style=social&label=Star)](https://github.com/dev-five-git/vespera)
[![GitHub forks](https://img.shields.io/github/forks/dev-five-git/vespera.svg?style=social&label=Fork)](https://github.com/dev-five-git/vespera/fork)
[![GitHub issues](https://img.shields.io/github/issues/dev-five-git/vespera.svg)](https://github.com/dev-five-git/vespera/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/dev-five-git/vespera.svg)](https://github.com/dev-five-git/vespera/pulls)
[![GitHub last commit](https://img.shields.io/github/last-commit/dev-five-git/vespera.svg)](https://github.com/dev-five-git/vespera/commits/main)
[![OpenAPI](https://img.shields.io/badge/OpenAPI-3.1-green.svg)](https://www.openapis.org/)

---

## Introduction

Vespera is a fully automated OpenAPI engine for Axum — delivering a FastAPI-like developer experience to the Rust ecosystem.

It automatically discovers routes, imports handlers and schemas, and generates a complete OpenAPI 3.1 specification with zero configuration.

Just write your Axum API.  
Vespera handles the rest.

---

## Features

### 1. Zero-Config Route Discovery
Automatically scans Axum routers and submodules to detect all registered routes.

### 2. Auto-Import of Handlers and Schemas
Automatically pulls in handlers, request/response types, and data models into the OpenAPI spec.

### 3. Fully Automated OpenAPI Engine
Generates a complete OpenAPI 3.1 document from:
- Routes
- Extractors
- Parameters
- Request bodies
- Response bodies
- Rust data structures (Serde)

### 4. Type-Safe Schema Extraction
Rust types are converted into JSON Schema with full type fidelity.

### 5. Built-in Swagger UI
Automatically generates and serves Swagger UI documentation when `docs_url` is specified, providing interactive API exploration.

### 6. Axum-First Design
Built specifically for Axum's architecture while offering the productivity of modern API frameworks.

---

## Example

### Routes Auto Import

```rust
use axum::{Router, routing::get};
use vespera::vespera;
use axum::Json;

async fn health() -> &'static str {
    "ok"
}

async fn get_user(id: u32) -> Json<User> {
    Json(User { id, name: "Alice".into() })
}

#[tokio::main]
async fn main() {
    dotenv().ok();

    let config = Config::from_env();
    let port = config.port;
    let db = create_db_connection(&config.database_url).await;

    let state = AppState { db, config };

    let app = vespera!(
        openapi = "openapi.json",
        title = "My API",
        version = "1.0.0",
        docs_url = "/docs"
    )
    .with_state(state)
    .layer(
        CorsLayer::new()
            .allow_origin("http://localhost:3000".parse::<HeaderValue>().unwrap())
            .allow_methods([
                Method::GET,
                Method::POST,
                Method::PUT,
                Method::DELETE,
                Method::OPTIONS,
            ])
            .allow_headers([
                axum::http::header::CONTENT_TYPE,
                axum::http::header::AUTHORIZATION,
            ]),
    );

    let addr = SocketAddr::from(([0, 0, 0, 0], port));
    println!("API server is running on port {}", port);
    println!("Swagger UI available at http://localhost:{}/docs", port);
    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
    axum::serve(listener, app).await.unwrap();
}
```

---

## Installation

Add the following to your `Cargo.toml`:

```toml
[dependencies]
vespera = "0.1.0"
axum = "0.8"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
```

---

## Quick Start

### 1. Create Project Structure

Create a `src/routes` folder in your project root and write route handlers:

```
src/
├── main.rs
└── routes/
    ├── mod.rs
    ├── users.rs
    └── posts.rs
```

### 2. Write Route Handlers

`src/routes/users.rs`:

```rust
use axum::{Json, Path, State};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct User {
    pub id: u32,
    pub name: String,
}

/// `/users/{id}` - default method is get
#[vespera::route(path = "/{id}")]
pub async fn get_user(
    State(state): State<AppState>,
    Path(id): Path<i32>) -> Json<User> {
    Json(User {
        id,
        name: "Alice".into(),
    })
}

/// /users
#[vespera::route(method = "post")]
pub async fn create_user(Json(user): Json<User>) -> Json<User> {
    Json(user)
}
```

### 3. Register Modules

`src/routes/mod.rs`:

```rust
pub mod users;
pub mod posts;
```

### 4. Setup Main Application

`src/main.rs`:

```rust
use vespera::vespera;

#[tokio::main]
async fn main() {
    // Basic usage: scans "routes" folder by default
    let app = vespera!();
    
    // Or with OpenAPI and Swagger UI support
    let app = vespera!(
        openapi = "openapi.json",
        title = "My API",
        version = "1.0.0",
        docs_url = "/docs"
    );
    
    // Or specify a custom folder: vespera!("api")
    
    let addr = std::net::SocketAddr::from(([0, 0, 0, 0], 3000));
    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
    println!("Server running on http://localhost:3000");
    println!("Swagger UI available at http://localhost:3000/docs");
    axum::serve(listener, app).await.unwrap();
}
```

---

## Usage

### `vespera!` Macro

Automatically scans routes and generates an Axum Router with optional OpenAPI and Swagger UI support.

```rust
// Basic usage: scans "routes" folder
let app = vespera!();

// Specify a custom folder
let app = vespera!("api");

// With OpenAPI JSON file generation
let app = vespera!(
    openapi = "openapi.json"
);

// Generate multiple OpenAPI JSON files at once
let app = vespera!(
    openapi = ["openapi.json", "admin-openapi.json"]
);

// With OpenAPI and Swagger UI
let app = vespera!(
    openapi = "openapi.json",
    docs_url = "/docs"
);

// Full configuration with all parameters
let app = vespera!(
    dir = "routes",              // Route folder name (default: "routes")
    openapi = "openapi.json",    // OpenAPI JSON file path (optional)
    title = "My API",            // API title (optional, default: "API")
    version = "1.0.0",           // API version (optional, default: "1.0.0")
    docs_url = "/docs"           // Swagger UI documentation URL (optional)
);
```

#### Parameter Description

- **`dir`**: Route folder name (default: `"routes"`)
  - You can also specify it directly as a string literal: `vespera!("api")`
  
- **`openapi`**: OpenAPI JSON file path(s) (optional)
  - Accepts a single string or an array of strings
  - If specified, an OpenAPI 3.1 spec is generated at compile time and **writes an `openapi.json` file to the specified path (or paths)**
  - Example: `openapi = "openapi.json"` → creates `openapi.json` file in project root
  - Example: `openapi = "docs/api.json"` → creates `docs/api.json` file
  - Example: `openapi = ["openapi.json", "docs/admin.json"]` → writes both files
  
- **`title`**: API title (optional, default: `"API"`)
  - Used in the `info.title` field of the OpenAPI document
  
- **`version`**: API version (optional, default: `"1.0.0"`)
  - Used in the `info.version` field of the OpenAPI document
  
- **`docs_url`**: Swagger UI documentation URL (optional)
  - If specified, you can view the API documentation through Swagger UI at that path
  - Example: Setting `docs_url = "/docs"` allows viewing documentation at `http://localhost:3000/docs`

### `#[route]` Attribute Macro

Specify HTTP method and path for handler functions.

```rust
// GET request
#[vespera::route(get)]
pub async fn list_users() -> Json<Vec<User>> {
    // ...
}

// POST request (custom path)
#[vespera::route(post, path = "/users")]
pub async fn create_user(Json(user): Json<User>) -> Json<User> {
    // ...
}

// Path parameter support
#[vespera::route(get, path = "/users/:id")]
pub async fn get_user(id: u32) -> Json<User> {
    // ...
}
```

### Supported HTTP Methods

- `GET`
- `POST`
- `PUT`
- `PATCH`
- `DELETE`
- `HEAD`
- `OPTIONS`

### OpenAPI JSON Generation and Swagger UI

When you specify the `openapi` parameter in the `vespera!` macro, an OpenAPI 3.1 spec is automatically generated at compile time and **writes a file to the specified path**.

```rust
let app = vespera!(
    openapi = "openapi.json",    // Creates openapi.json file at this path
    title = "My API",            // API title
    version = "1.0.0",           // API version
    docs_url = "/docs"           // Swagger UI URL (optional)
);
```

With this configuration:
- An OpenAPI JSON file is automatically generated at the specified path during compilation
  - `openapi = "openapi.json"` → creates `openapi.json` file in project root
  - `openapi = "docs/api.json"` → creates `docs/api.json` file
- If you specify `docs_url`, you can view the API documentation through Swagger UI at that path
- The OpenAPI spec is automatically generated by analyzing routes, handlers, and request/response types

**Note**: The `build.rs` file is no longer needed. The `vespera!` macro automatically handles it at compile time.

### File Structure and Route Mapping

File structure is automatically converted to URL paths:

```
routes/
├── users.rs          → /users
├── posts.rs          → /posts
└── admin/
    └── users.rs      → /admin/users
```

---

## Project Structure

```
vespera/
├── Cargo.toml
├── README.md
└── crates/
    └── vespera/
        ├── Cargo.toml
        └── src/
            ├── lib.rs          # Main macro definitions
            ├── args.rs         # Macro argument parsing
            ├── file_utils.rs   # File system utilities
            ├── method.rs       # HTTP method definitions
            └── route/
                ├── mod.rs
                └── utils.rs    # Route information extraction
```

---

## How It Works

1. **Compile-Time Scanning**: The `vespera!` macro scans the specified folder to discover all route handlers.

2. **Attribute Parsing**: Extracts HTTP method and path information from each handler's `#[route]` attribute.

3. **Code Generation**: Automatically generates Axum Router code based on discovered routes.

4. **Type Safety**: Leverages Rust's type system to ensure all routes are correctly registered at compile time.

---

## Contributing

Contributions are welcome! Please open an issue or submit a Pull Request.

### Development Setup

```bash
# Clone the repository
git clone https://github.com/yourusername/vespera.git
cd vespera

# Build
cargo build

# Run tests
cargo test
```

---

## License

This project is licensed under the Apache 2.0 License. See the `LICENSE` file for details.

---

## Roadmap

- [x] Automatic routes importing
- [x] Automatic OpenAPI 3.1 spec generation (via `vespera!` macro)
- [x] Automatic request/response schema extraction
- [x] Swagger UI integration
- [ ] Support for more Axum extractors

---

## Acknowledgments

Vespera is inspired by FastAPI’s developer experience and also takes inspiration from Next.js, all designed for the Rust ecosystem.