astrea_macro/lib.rs
1//! Astrea procedural macros
2//!
3//! / Astrea 过程宏
4//!
5//! This crate provides the procedural macros used by Astrea:
6//!
7//! 此 crate 提供 Astrea 使用的宏:
8//!
9//! - [`route`] - Attribute macro for marking route handlers
10//! [`route`] - 标记路由处理函数的属性宏
11//! - [`generate_routes!`] - Macro for generating routes from filesystem
12//! [`generate_routes!`] - 从文件系统生成路由的宏
13//!
14//! # Example
15//!
16//! # 示例
17//!
18//! ```rust,ignore
19//! // routes/index.get.rs
20//! use astrea::prelude::*;
21//!
22//! #[route]
23//! pub async fn handler(event: Event) -> Result<Response> {
24//! json(json!({"message": "Hello"}))
25//! }
26//! ```
27
28mod codegen;
29#[cfg(feature = "openapi")]
30mod openapi;
31mod parser;
32mod route;
33mod scanner;
34mod utils;
35
36use proc_macro::TokenStream;
37
38// ============================================================================
39// #[route] attribute macro
40// ============================================================================
41// #[route] 属性宏
42// ============================================================================
43
44/// Attribute macro for Astrea route handlers
45///
46/// / Astrea 路由处理函数的属性宏
47///
48/// Transforms simple `async fn handler(event: Event)` functions into
49/// Axum-compatible handlers with automatic error handling.
50///
51/// 将简单的 `async fn handler(event: Event)` 函数转换为
52/// Axum 兼容的处理函数,具有自动错误处理功能。
53///
54/// # Requirements
55///
56/// # 要求
57///
58/// - The function must be `async`
59/// 函数必须是 `async`
60/// - The function must take `event: Event` as the first parameter
61/// 函数必须以 `event: Event` 作为第一个参数
62/// - The function must return `Result<Response>`
63/// 函数必须返回 `Result<Response>`
64///
65/// # Example
66///
67/// # 示例
68///
69/// ```rust,ignore
70/// use astrea::prelude::*;
71///
72/// #[route]
73/// pub async fn handler(event: Event) -> Result<Response> {
74/// let name = get_param(&event, "name").unwrap_or("World");
75/// json(json!({ "message": format!("Hello, {}!", name) }))
76/// }
77/// ```
78///
79/// # Generated Code
80///
81/// # 生成的代码
82///
83/// The macro generates a wrapper function that:
84///
85/// 宏生成一个包装函数,它:
86///
87/// - Extracts Axum request data (method, URI, headers, params, query, body)
88/// 提取 Axum 请求数据(方法、URI、头、参数、查询、体)
89/// - Creates an `Event` struct
90/// 创建 `Event` 结构体
91/// - Calls your handler function
92/// 调用你的处理函数
93/// - Automatically converts `Result<Response>` to Axum's response type
94/// 自动将 `Result<Response>` 转换为 Axum 的响应类型
95#[proc_macro_attribute]
96pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
97 route::impl_route(args, input)
98}
99
100// ============================================================================
101// generate_routes! macro — with middleware support
102// ============================================================================
103// generate_routes! 宏 — 支持中间件
104// ============================================================================
105
106/// Procedural macro to generate routes from filesystem
107///
108/// / 从文件系统生成路由的过程宏
109///
110/// Scans the `routes` directory at compile time and generates route
111/// registration code, eliminating the need for manual route definitions
112/// or `build.rs` scripts.
113///
114/// 在编译时扫描 `routes` 目录并生成路由注册代码,
115/// 无需手动定义路由或编写 `build.rs` 脚本。
116///
117/// # Middleware Support
118///
119/// # 中间件支持
120///
121/// Place `_middleware.rs` files in route directories to define scoped middleware.
122/// Each file must export `pub fn middleware() -> astrea::middleware::Middleware`.
123///
124/// 在路由目录中放置 `_middleware.rs` 文件来定义作用域中间件。
125/// 每个文件必须导出 `pub fn middleware() -> astrea::middleware::Middleware`。
126///
127/// ## Proximity Principle (就近原则)
128///
129/// Middleware closest to the route handler applies first (innermost layer).
130/// Parent middleware wraps child middleware (outermost layer).
131///
132/// 最靠近路由处理函数的中间件最先应用(最内层)。
133/// 父中间件包裹子中间件(最外层)。
134///
135/// ## Extend vs Override (叠加 vs 覆盖)
136///
137/// - **Extend** (default): child middleware stacks on parent middleware
138/// **叠加**(默认):子中间件叠加在父中间件之上
139/// - **Override**: child middleware replaces parent middleware entirely
140/// **覆盖**:子中间件完全替换父中间件
141///
142/// # Usage
143///
144/// # 用法
145///
146/// ```rust,ignore
147/// mod routes {
148/// astrea::generate_routes!();
149/// }
150/// ```
151///
152/// # File Convention
153///
154/// # 文件约定
155///
156/// ```text
157/// routes/
158/// ├── _middleware.rs # Global middleware / 全局中间件
159/// ├── index.get.rs # GET /
160/// ├── api/
161/// │ ├── _middleware.rs # API middleware (extends root) / API 中间件(叠加)
162/// │ ├── users.get.rs # GET /api/users ← root + API middleware
163/// │ └── public/
164/// │ ├── _middleware.rs # Public middleware (overrides) / 公开中间件(覆盖)
165/// │ └── health.get.rs # GET /api/public/health ← public middleware only
166/// └── posts/
167/// └── index.post.rs # POST /posts ← root middleware only
168/// ```
169#[proc_macro]
170pub fn generate_routes(input: TokenStream) -> TokenStream {
171 codegen::impl_generate_routes(input)
172}