doido_controller_macros/lib.rs
1mod codegen;
2mod controller;
3mod parser;
4
5use proc_macro::TokenStream;
6use syn::parse_macro_input;
7
8/// Expands the `routes!` DSL (verbs, `resources!`, `namespace!`, `scope!`)
9/// into an `axum::Router`. Merged in from the former `doido-router` crate.
10#[proc_macro]
11pub fn routes(input: TokenStream) -> TokenStream {
12 let parsed = parse_macro_input!(input as parser::RoutesInput);
13 codegen::generate(parsed).into()
14}
15
16/// Marks an impl block as a controller. Rewrites action methods into
17/// axum-compatible handlers, wiring in any filters.
18///
19/// Filters are declared with the `#[before_action(...)]` / `#[after_action(...)]`
20/// **helper attributes** on action methods; this macro parses and consumes them
21/// while expanding the impl block, so there are no standalone
22/// `before_action`/`after_action` macros to import:
23///
24/// ```ignore
25/// #[controller]
26/// impl PostsController {
27/// #[before_action(require_auth)]
28/// #[before_action(load_record, only = [show, edit])]
29/// #[after_action(log_response)]
30/// async fn show(ctx: &mut Context) -> Response { /* ... */ }
31/// }
32/// ```
33///
34/// `before_action` filters run in declaration order before the action and may
35/// short-circuit by returning `Err(response)`; `after_action` filters run after.
36#[proc_macro_attribute]
37pub fn controller(attr: TokenStream, item: TokenStream) -> TokenStream {
38 match controller::expand_controller(attr.into(), item.into()) {
39 Ok(ts) => ts.into(),
40 Err(e) => e.to_compile_error().into(),
41 }
42}