resuma_macros/lib.rs
1//! Resuma procedural macros.
2//!
3//! Re-exported by the [`resuma`](https://docs.rs/resuma) crate. Typical surface:
4//!
5//! | Macro | Role |
6//! |-------|------|
7//! | [`view!`] | JSX-like templates → [`View`](https://docs.rs/resuma/latest/resuma/enum.View.html) |
8//! | [`#[component]`](component) | Resumable component + props builder (lazy handler boundary) |
9//! | [`#[server]`](server) | Async RPC at `POST /_resuma/action/:name` |
10//! | [`#[data]`](data) | Concise typed DTO/model helper |
11//! | [`computed!`](computed) | Client-replayable derived signal (rs2js) |
12//! | [`effect!`](effect) | Client-replayable side effect (rs2js) |
13//! | [`debounce!`](debounce) | Debounced client reaction |
14//! | [`#[island]`](island) | Optional heavy lazy boundary (`load = "visible"`) |
15//! | [`js!`](js) | Raw JavaScript handler escape hatch |
16
17mod component_macro;
18mod computed_macro;
19mod data_macro;
20mod debounce_macro;
21mod effect_macro;
22mod extract_codegen;
23mod island_macro;
24mod js_macro;
25mod layout_macro;
26mod load_macro;
27mod middleware_macro;
28mod rs2js;
29mod server_macro;
30mod store_macro;
31mod submit_macro;
32mod view_macro;
33mod worker_macro;
34
35use proc_macro::TokenStream;
36
37/// `view!` — JSX-like template macro.
38#[proc_macro]
39pub fn view(input: TokenStream) -> TokenStream {
40 view_macro::expand(input.into()).into()
41}
42
43/// `#[component]` — resumable component with generated props builder.
44///
45/// Wraps output in a lazy handler boundary; event handlers register under
46/// `/_resuma/handler/{ComponentName}.js`. For heavy optional lazy bundles, see [`island`].
47#[proc_macro_attribute]
48pub fn component(args: TokenStream, input: TokenStream) -> TokenStream {
49 component_macro::expand(args.into(), input.into()).into()
50}
51
52/// `#[server]` — exposes an async fn as a server action.
53#[proc_macro_attribute]
54pub fn server(args: TokenStream, input: TokenStream) -> TokenStream {
55 server_macro::expand(args.into(), input.into()).into()
56}
57
58/// `#[data]` — concise DTO/model helper for Resuma data structs and enums.
59#[proc_macro_attribute]
60pub fn data(args: TokenStream, input: TokenStream) -> TokenStream {
61 data_macro::expand(args.into(), input.into()).into()
62}
63
64/// `#[island]` — optional interactive boundary for heavy or visibility-gated JS.
65///
66/// Most UI only needs [`component`]. Use islands for large client bundles,
67/// `#[island(load = "visible")]`, or dev HMR refresh via `GET /_resuma/island/:instance`.
68#[proc_macro_attribute]
69pub fn island(args: TokenStream, input: TokenStream) -> TokenStream {
70 island_macro::expand(args.into(), input.into()).into()
71}
72
73/// `#[load]` — Resuma Flow server data loader.
74#[proc_macro_attribute]
75pub fn load(args: TokenStream, input: TokenStream) -> TokenStream {
76 load_macro::expand(args.into(), input.into()).into()
77}
78
79/// `#[submit]` — Resuma Flow form submission handler.
80#[proc_macro_attribute]
81pub fn submit(args: TokenStream, input: TokenStream) -> TokenStream {
82 submit_macro::expand(args.into(), input.into()).into()
83}
84
85/// `#[layout]` — Resuma Flow layout wrapper.
86#[proc_macro_attribute]
87pub fn layout(args: TokenStream, input: TokenStream) -> TokenStream {
88 layout_macro::expand(args.into(), input.into()).into()
89}
90
91/// `#[middleware]` — Resuma Flow request middleware.
92#[proc_macro_attribute]
93pub fn middleware(args: TokenStream, input: TokenStream) -> TokenStream {
94 middleware_macro::expand(args.into(), input.into()).into()
95}
96
97/// `#[worker]` — registers an async fn as a Resuma execution worker.
98///
99/// ```ignore
100/// #[worker(intent = "analyze leads")]
101/// async fn lead_agent(input: Value, ctx: WorkerContext) -> Result<Value> { ... }
102/// ```
103#[proc_macro_attribute]
104pub fn worker(args: TokenStream, input: TokenStream) -> TokenStream {
105 worker_macro::expand(args.into(), input.into()).into()
106}
107
108/// `js!` — raw JavaScript escape hatch for event handlers.
109#[proc_macro]
110pub fn js(input: TokenStream) -> TokenStream {
111 js_macro::expand(input.into()).into()
112}
113
114/// `computed!([deps…], move || …)` — derived signal with client replay (rs2js-translated).
115///
116/// Runs during SSR and replays in the browser when dependencies change.
117/// For SSR-only derived state, use [`use_computed`](https://docs.rs/resuma/latest/resuma/fn.use_computed.html) instead.
118#[proc_macro]
119pub fn computed(input: TokenStream) -> TokenStream {
120 computed_macro::expand(input.into()).into()
121}
122
123/// `effect!([signals…], move || { … })` — client-replayable side effect (rs2js).
124#[proc_macro]
125pub fn effect(input: TokenStream) -> TokenStream {
126 effect_macro::expand(input.into()).into()
127}
128
129#[proc_macro_derive(Store)]
130pub fn derive_store(input: TokenStream) -> TokenStream {
131 store_macro::derive(input)
132}
133
134/// `debounce!([deps…], ms, move || …)` — debounced client reaction (rs2js-translated).
135///
136/// ```ignore
137/// debounce!([search], 300, move || { /* runs after search settles */ });
138/// ```
139#[proc_macro]
140pub fn debounce(input: TokenStream) -> TokenStream {
141 debounce_macro::expand(input.into()).into()
142}