forge_macros/lib.rs
1use proc_macro::TokenStream;
2
3mod action;
4mod cron;
5mod enum_type;
6mod job;
7mod model;
8mod mutation;
9mod query;
10mod workflow;
11
12/// Marks a struct as a FORGE model, generating schema metadata for TypeScript codegen.
13///
14/// # Example
15/// ```ignore
16/// #[forge::model]
17/// pub struct User {
18/// pub id: Uuid,
19/// pub email: String,
20/// pub name: String,
21/// pub created_at: DateTime<Utc>,
22/// }
23/// ```
24#[proc_macro_attribute]
25pub fn model(attr: TokenStream, item: TokenStream) -> TokenStream {
26 model::expand_model(attr, item)
27}
28
29/// Marks an enum for database storage as a PostgreSQL ENUM type.
30///
31/// # Example
32/// ```ignore
33/// #[forge::forge_enum]
34/// pub enum ProjectStatus {
35/// Draft,
36/// Active,
37/// Paused,
38/// Completed,
39/// }
40/// ```
41#[proc_macro_attribute]
42pub fn forge_enum(attr: TokenStream, item: TokenStream) -> TokenStream {
43 enum_type::expand_enum(attr, item)
44}
45
46/// Marks a function as a query (read-only, cacheable, subscribable).
47///
48/// # Attributes
49/// - `cache = "5m"` - Cache TTL (duration like "30s", "5m", "1h")
50/// - `public` - No authentication required
51/// - `require_auth` - Require authentication
52/// - `timeout = 30` - Timeout in seconds
53///
54/// # Example
55/// ```ignore
56/// #[forge::query]
57/// pub async fn get_user(ctx: &QueryContext, user_id: Uuid) -> Result<User> {
58/// // ...
59/// }
60///
61/// #[forge::query(cache = "5m", require_auth)]
62/// pub async fn get_profile(ctx: &QueryContext) -> Result<Profile> {
63/// let user_id = ctx.require_user_id()?;
64/// // ...
65/// }
66/// ```
67#[proc_macro_attribute]
68pub fn query(attr: TokenStream, item: TokenStream) -> TokenStream {
69 query::expand_query(attr, item)
70}
71
72/// Marks a function as a mutation (transactional write).
73///
74/// Mutations run within a database transaction. All changes commit together or roll back on error.
75///
76/// # Attributes
77/// - `require_auth` - Require authentication
78/// - `require_role("admin")` - Require specific role
79/// - `timeout = 30` - Timeout in seconds
80///
81/// # Example
82/// ```ignore
83/// #[forge::mutation]
84/// pub async fn create_project(ctx: &MutationContext, input: CreateProjectInput) -> Result<Project> {
85/// let user_id = ctx.require_user_id()?;
86/// // ...
87/// }
88/// ```
89#[proc_macro_attribute]
90pub fn mutation(attr: TokenStream, item: TokenStream) -> TokenStream {
91 mutation::expand_mutation(attr, item)
92}
93
94/// Marks a function as an action (side effects, external APIs).
95///
96/// Actions can call external APIs and perform side effects. NOT transactional.
97///
98/// # Attributes
99/// - `require_auth` - Require authentication
100/// - `require_role("admin")` - Require specific role
101/// - `timeout = 60` - Timeout in seconds
102///
103/// # Example
104/// ```ignore
105/// #[forge::action(timeout = 60)]
106/// pub async fn sync_with_stripe(ctx: &ActionContext, user_id: Uuid) -> Result<SyncResult> {
107/// let customer = ctx.http().get("https://api.stripe.com/...").await?;
108/// // ...
109/// }
110/// ```
111#[proc_macro_attribute]
112pub fn action(attr: TokenStream, item: TokenStream) -> TokenStream {
113 action::expand_action(attr, item)
114}
115
116/// Marks a function as a background job.
117///
118/// Jobs are durable background tasks that survive server restarts and automatically retry on failure.
119///
120/// # Attributes
121/// - `timeout = "30m"` - Job timeout
122/// - `priority = "normal"` - background, low, normal, high, critical
123/// - `max_attempts = 3` - Maximum retry attempts
124/// - `worker_capability = "general"` - Required worker capability
125///
126/// # Example
127/// ```ignore
128/// #[forge::job]
129/// #[timeout = "30m"]
130/// #[priority = "high"]
131/// pub async fn send_welcome_email(ctx: &JobContext, input: SendEmailInput) -> Result<()> {
132/// // ...
133/// }
134/// ```
135#[proc_macro_attribute]
136pub fn job(attr: TokenStream, item: TokenStream) -> TokenStream {
137 job::job_impl(attr, item)
138}
139
140/// Marks a function as a scheduled cron task.
141///
142/// Cron jobs run on a schedule, exactly once per scheduled time across the cluster.
143///
144/// # Attributes
145/// - `timezone = "UTC"` - Timezone for the schedule
146/// - `catch_up` - Run missed executions after downtime
147/// - `timeout = "1h"` - Execution timeout
148///
149/// # Example
150/// ```ignore
151/// #[forge::cron("0 0 * * *")]
152/// #[timezone = "UTC"]
153/// #[catch_up]
154/// pub async fn daily_cleanup(ctx: &CronContext) -> Result<()> {
155/// // ...
156/// }
157/// ```
158#[proc_macro_attribute]
159pub fn cron(attr: TokenStream, item: TokenStream) -> TokenStream {
160 cron::cron_impl(attr, item)
161}
162
163/// Marks a function as a durable workflow.
164///
165/// Workflows are multi-step processes that survive restarts and handle failures with compensation.
166///
167/// # Attributes
168/// - `version = 1` - Workflow version (increment for breaking changes)
169/// - `timeout = "24h"` - Maximum execution time
170///
171/// # Example
172/// ```ignore
173/// #[forge::workflow]
174/// #[version = 1]
175/// pub async fn user_onboarding(ctx: &WorkflowContext, input: OnboardingInput) -> Result<OnboardingResult> {
176/// let user = ctx.step("create_user", || async { /* ... */ }).await?;
177/// ctx.step("send_welcome", || async { /* ... */ }).await;
178/// Ok(OnboardingResult { user })
179/// }
180/// ```
181#[proc_macro_attribute]
182pub fn workflow(attr: TokenStream, item: TokenStream) -> TokenStream {
183 workflow::workflow_impl(attr, item)
184}