fastapi_macros/lib.rs
1//! Procedural macros for fastapi_rust.
2//!
3//! This crate provides the following macros:
4//!
5//! - Route macros: `#[get]`, `#[post]`, `#[put]`, `#[delete]`, `#[patch]`, `#[head]`, `#[options]`
6//! - `#[derive(Validate)]` for compile-time validation
7//! - `#[derive(JsonSchema)]` for OpenAPI schema generation
8//!
9//! # Role In The System
10//!
11//! `fastapi-macros` is the compile-time glue that keeps the runtime minimal.
12//! It analyzes handler signatures, generates route registration metadata, and
13//! enforces validation/schema rules without any runtime reflection. The emitted
14//! code targets types from `fastapi-core` and `fastapi-openapi`, and is re-exported
15//! by the `fastapi` facade crate for user ergonomics.
16//!
17//! # Example
18//!
19//! ```ignore
20//! use fastapi::prelude::*;
21//!
22//! #[get("/items/{id}")]
23//! async fn get_item(cx: &Cx, id: Path<i64>) -> Json<Item> {
24//! // ...
25//! }
26//! ```
27
28use proc_macro::TokenStream;
29
30mod openapi;
31mod param;
32mod response_model;
33mod route;
34mod validate;
35
36/// Mark a function as a GET handler.
37///
38/// # Example
39///
40/// ```ignore
41/// #[get("/items")]
42/// async fn list_items() -> Json<Vec<Item>> {
43/// // ...
44/// }
45/// ```
46#[proc_macro_attribute]
47pub fn get(attr: TokenStream, item: TokenStream) -> TokenStream {
48 route::route_impl("Get", attr, item)
49}
50
51/// Mark a function as a POST handler.
52#[proc_macro_attribute]
53pub fn post(attr: TokenStream, item: TokenStream) -> TokenStream {
54 route::route_impl("Post", attr, item)
55}
56
57/// Mark a function as a PUT handler.
58#[proc_macro_attribute]
59pub fn put(attr: TokenStream, item: TokenStream) -> TokenStream {
60 route::route_impl("Put", attr, item)
61}
62
63/// Mark a function as a DELETE handler.
64#[proc_macro_attribute]
65pub fn delete(attr: TokenStream, item: TokenStream) -> TokenStream {
66 route::route_impl("Delete", attr, item)
67}
68
69/// Mark a function as a PATCH handler.
70#[proc_macro_attribute]
71pub fn patch(attr: TokenStream, item: TokenStream) -> TokenStream {
72 route::route_impl("Patch", attr, item)
73}
74
75/// Mark a function as a HEAD handler.
76///
77/// HEAD requests are identical to GET but return only headers, not body.
78/// Useful for checking resource existence or metadata without full content.
79///
80/// # Example
81///
82/// ```ignore
83/// #[head("/items/{id}")]
84/// async fn head_item(id: Path<i64>) -> StatusCode {
85/// StatusCode::OK
86/// }
87/// ```
88#[proc_macro_attribute]
89pub fn head(attr: TokenStream, item: TokenStream) -> TokenStream {
90 route::route_impl("Head", attr, item)
91}
92
93/// Mark a function as an OPTIONS handler.
94///
95/// OPTIONS requests return allowed methods and CORS headers for a resource.
96///
97/// # Example
98///
99/// ```ignore
100/// #[options("/items")]
101/// async fn options_items() -> Response {
102/// Response::builder()
103/// .header("Allow", "GET, POST, OPTIONS")
104/// .body(())
105/// }
106/// ```
107#[proc_macro_attribute]
108pub fn options(attr: TokenStream, item: TokenStream) -> TokenStream {
109 route::route_impl("Options", attr, item)
110}
111
112/// Derive validation for a struct.
113///
114/// # Validation Attributes
115///
116/// - `#[validate(length(min = 1, max = 100))]` - String length
117/// - `#[validate(range(min = 0.0, max = 1.0))]` - Numeric range
118/// - `#[validate(email)]` - Email format
119/// - `#[validate(regex = "pattern")]` - Regex pattern
120///
121/// # Example
122///
123/// ```ignore
124/// #[derive(Validate)]
125/// struct CreateUser {
126/// #[validate(length(min = 1, max = 50))]
127/// name: String,
128/// #[validate(email)]
129/// email: String,
130/// }
131/// ```
132#[proc_macro_derive(Validate, attributes(validate))]
133pub fn derive_validate(input: TokenStream) -> TokenStream {
134 validate::derive_validate_impl(input)
135}
136
137/// Derive JSON Schema for OpenAPI.
138///
139/// # Example
140///
141/// ```ignore
142/// #[derive(JsonSchema)]
143/// struct Item {
144/// id: i64,
145/// name: String,
146/// #[schema(nullable)]
147/// description: Option<String>,
148/// }
149/// ```
150#[proc_macro_derive(JsonSchema, attributes(schema))]
151pub fn derive_json_schema(input: TokenStream) -> TokenStream {
152 openapi::derive_json_schema_impl(input)
153}
154
155/// Derive response model alias metadata for FastAPI-compatible `by_alias` handling.
156///
157/// This emits an implementation of `fastapi_core::ResponseModelAliases` using
158/// `#[serde(rename = ...)]` and `#[serde(rename_all = ...)]` attributes.
159#[proc_macro_derive(ResponseModelAliases, attributes(serde))]
160pub fn derive_response_model_aliases(input: TokenStream) -> TokenStream {
161 response_model::derive_response_model_aliases_impl(input)
162}