sword-macros 0.1.1

Axum based web framework prototype macros (sword crate)
Documentation
<div align="center">
<img src="https://pillan.inf.uct.cl/~lrevillod/images/sword-logo.webp" alt="Sword Logo" width="200">

<h1>โš”๏ธ Sword โš”๏ธ</h1>
<p><em>A prototype for a rust web framework</em></p>

---

> **๐Ÿšง Prototype Status**
> 
> This is a **prototype** and **not production-ready**. It is intended for:
> - ๐Ÿ“š **Educational purposes**
> - ๐Ÿ”ฌ **Exploring web framework design**
> - ๐Ÿ› ๏ธ **Axum wrapper experimentation**
> 
> While it may scale well in the future, **it is not recommended for production use** at this stage.

---

</div>

## โœจ Features

- ๐Ÿ›ฃ๏ธ **Macro-based routing** - Clean and intuitive route definitions
- ๐Ÿ” **Complex query parameters** - Ready for advanced parameter handling
- ๐Ÿ“„ **JSON-first design** - Built with JSON formats as priority
- โœ… **Built-in validation** - Support with `serde` and `validator` crates
- ๐ŸŒ **RFC-compliant HTTP responses** - Using `axum_responses` crate
- ๐Ÿ’ก **Express-Like** - It provides a `req` from request with some utility methods.

## ๐Ÿ› ๏ธ Usage

### Basic web server 

```rust
use sword::prelude::*;

#[controller("/")]
struct AppController {}

#[controller_impl]
impl AppController {
    #[get("/")]
    async fn get_data() -> HttpResponse {
        let data = vec![
            "This is a basic web server",
            "It serves static data",
            "You can extend it with more routes",
        ];

        HttpResponse::Ok().data(data)
    }

    #[get("/hello")]
    async fn hello() -> HttpResponse {
        HttpResponse::Ok().data("Hello, World!")
    }

    #[post("/submit")]
    async fn submit_data(req: Request) -> Result<HttpResponse> {
        let body = req.body::<serde_json::Value>()?;

        Ok(HttpResponse::Ok()
            .data(body)
            .message("Data submitted successfully"))
    }
}

#[tokio::main]
async fn main() {
    Application::builder()
        .controller::<AppController>()
        .run("0.0.0.0:8080")
        .await;
}

```

### With Middleware

```rust
use serde_json::json;
use std::sync::{Arc, OnceLock};
use sword::prelude::*;
use tokio::sync::RwLock;

type InMemoryDb = Arc<RwLock<Vec<String>>>;
const IN_MEMORY_DB: OnceLock<InMemoryDb> = OnceLock::new();

fn db() -> Arc<RwLock<Vec<String>>> {
    IN_MEMORY_DB
        .get_or_init(|| Arc::new(RwLock::new(Vec::new())))
        .clone()
}

#[derive(Clone)]
struct AppState {
    db: InMemoryDb,
}

struct MyMiddleware;

impl MiddlewareWithState<AppState> for MyMiddleware {
    async fn handle(ctx: State<AppState>, mut req: Request, next: Next) -> MiddlewareResult {
        let count = ctx.db.read().await.len();
        req.extensions.insert(count);

        Ok(next.run(req.into()).await)
    }
}

#[controller("/api")]
struct AppController {}

#[controller_impl]
impl AppController {
    #[get("/data")]
    #[middleware(MyMiddleware)]
    async fn submit_data(state: State<AppState>, req: Request) -> HttpResponse {
        let db = &state.db;
        let count = req.extensions.get::<usize>().cloned().unwrap_or(0);
        let message = format!("Current data count: {}", count);

        db.write().await.push(message);

        HttpResponse::Ok().data(json!({
            "count": count,
            "current_data": db.read().await.clone(),
        }))
    }
}

#[tokio::main]
async fn main() {
    let app_state = AppState { db: db() };

    Application::builder()
        .state(app_state)
        .controller::<AppController>()
        .run("0.0.0.0:8080")
        .await;
}

```

## Currently working on
- โœ…๐Ÿ“ฑ Add Application struct
- โœ… ๐Ÿ—๏ธ Add Application Context
- โœ… ๐Ÿ”’ Add Middleware support
- [ ] ๐Ÿ’‰ Add Dependency Injection support based on `shaku` crate

## ๐Ÿ“‹ Roadmap

- [ ] โš™๏ธ Add config file support
- [ ] ๐Ÿ“ Add File - FormData support
- [ ] ๐Ÿงช Add more tests
- [ ] ๐Ÿ“š Add more documentation
- [ ] ๐Ÿ› ๏ธ CLI Command line interface for code-generation (templates)