Skip to main content

salvo_craft/
lib.rs

1//! Modular handler crafting for Salvo web framework.
2//!
3//! This crate provides the `#[craft]` attribute macro that enables a more
4//! ergonomic way to define handlers as methods on structs, allowing for
5//! better code organization and state sharing.
6//!
7//! # Overview
8//!
9//! Instead of writing standalone handler functions, you can organize related
10//! handlers as methods on a struct, with shared state accessible via `self`:
11//!
12//! ```ignore
13//! use salvo::prelude::*;
14//! use salvo_craft::craft;
15//!
16//! #[derive(Clone)]
17//! pub struct UserService {
18//!     db: DatabasePool,
19//! }
20//!
21//! #[craft]
22//! impl UserService {
23//!     fn new(db: DatabasePool) -> Self {
24//!         Self { db }
25//!     }
26//!
27//!     #[craft(handler)]
28//!     async fn get_user(&self, id: PathParam<i64>) -> Result<Json<User>, StatusError> {
29//!         let user = self.db.get_user(*id).await?;
30//!         Ok(Json(user))
31//!     }
32//!
33//!     #[craft(handler)]
34//!     async fn list_users(&self) -> Json<Vec<User>> {
35//!         Json(self.db.list_users().await)
36//!     }
37//! }
38//! ```
39//!
40//! # Usage
41//!
42//! ## Basic Handler
43//!
44//! Use `#[craft(handler)]` to mark a method as a handler:
45//!
46//! ```ignore
47//! #[craft]
48//! impl MyService {
49//!     #[craft(handler)]
50//!     fn hello(&self) -> &'static str {
51//!         "Hello, World!"
52//!     }
53//! }
54//! ```
55//!
56//! ## With OpenAPI Support
57//!
58//! Use `#[craft(endpoint(...))]` for handlers that should be included in
59//! OpenAPI documentation:
60//!
61//! ```ignore
62//! #[craft]
63//! impl MyService {
64//!     #[craft(endpoint(tags("users"), status_codes(200, 404)))]
65//!     async fn get_user(&self, id: PathParam<i64>) -> Result<Json<User>, StatusError> {
66//!         // ...
67//!     }
68//! }
69//! ```
70//!
71//! # Method Receivers
72//!
73//! The `#[craft]` macro supports different method receivers:
74//!
75//! | Receiver | Requirement | Use Case |
76//! |----------|-------------|----------|
77//! | `&self` | Type must implement `Clone` | Most common, shared state |
78//! | `Arc<Self>` | None | Explicit reference counting |
79//! | None (static) | None | Stateless handlers |
80//!
81//! ## Examples
82//!
83//! ```ignore
84//! #[derive(Clone)]
85//! pub struct Service { /* ... */ }
86//!
87//! #[craft]
88//! impl Service {
89//!     // Uses &self - Service must be Clone
90//!     #[craft(handler)]
91//!     fn with_ref(&self) -> String { /* ... */ }
92//!
93//!     // Uses Arc<Self> - explicit shared ownership
94//!     #[craft(handler)]
95//!     fn with_arc(self: Arc<Self>) -> String { /* ... */ }
96//!
97//!     // Static method - no self
98//!     #[craft(handler)]
99//!     fn static_handler() -> String { /* ... */ }
100//! }
101//! ```
102//!
103//! # Router Integration
104//!
105//! Craft handlers are used with routers just like regular handlers:
106//!
107//! ```ignore
108//! let service = UserService::new(db_pool);
109//!
110//! let router = Router::new()
111//!     .push(Router::with_path("users/<id>").get(service.get_user()))
112//!     .push(Router::with_path("users").get(service.list_users()));
113//! ```
114
115pub use salvo_craft_macros::*;