1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! Procedural macros for stately state management
use TokenStream;
/// Implements the `HasName` trait for an entity struct.
///
/// This macro provides flexible name resolution for entities. The `StateEntity` trait
/// is automatically implemented by the `#[stately::state]` macro when the entity is
/// added to a state struct.
///
/// # Attributes
///
/// - `#[stately::entity]` - Uses the default "name" field
/// - `#[stately::entity(name_field = "field_name")]` - Uses a different field for the name
/// - `#[stately::entity(name_method = "method_name")]` - Calls a method to get the name
/// - `#[stately::entity(singleton)]` - For singleton entities, returns "default" as the name
///
/// # Examples
///
/// ```rust,ignore
/// // Default: uses the "name" field
/// #[stately::entity]
/// pub struct Pipeline {
/// pub name: String,
/// pub source: Link<SourceConfig>,
/// }
///
/// // Custom field name
/// #[stately::entity(name_field = "identifier")]
/// pub struct Config {
/// identifier: String,
/// }
///
/// // Custom method
/// #[stately::entity(name_method = "get_name")]
/// pub struct Task {
/// id: String,
/// }
/// impl Task {
/// fn get_name(&self) -> &str { &self.id }
/// }
/// ```
/// Generates application state with entity collections.
///
/// # Syntax
///
/// ```rust,ignore
/// #[stately::state]
/// pub struct AppState {
/// // Regular collections (many entities)
/// pipelines: Pipeline,
/// sources: SourceConfig,
///
/// // Singletons (one entity)
/// #[singleton]
/// parse_settings: BufferSettings,
/// }
/// ```
///
/// # OpenAPI
///
/// Optionally annotate the state and structures generated for automatic OpenAPI document
/// generation.
///
/// ```rust,ignore
/// #[stately::state(openapi)]
/// pub struct AppState {
/// pipelines: Pipeline,
/// }
/// ```
///
/// This generates a namespaced module (e.g., `axum_api`) with:
/// - Concrete response types with OpenAPI schemas
/// - Handler functions with OpenAPI path annotations
/// - A router function
/// - OpenAPI documentation attributes
///
/// # Generated Code
///
/// This generates:
/// - `StateEntry` enum with variants for each entity type
/// - `Entity` enum wrapping each entity for type erasure
/// - The state struct with collection fields
/// - (Optional) OpenAPI annotation
/// Generates Axum API integration for a state wrapper struct.
///
/// This macro allows you to create custom API state structs that wrap your stately state
/// along with additional dependencies (database pools, config, etc.), providing the CRUD endpoints
/// and events over `axum` APIs.
///
/// # Example
///
/// ```rust,ignore
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
/// use stately_derive::{state, axum_api};
///
/// #[stately::entity]
/// pub struct Pipeline {
/// pub name: String,
/// pub source: Link<SourceConfig>,
/// }
///
/// #[state(openapi)]
/// pub struct AppState {
/// pipelines: Pipeline,
/// }
///
/// #[axum_api(AppState, openapi(components = [Pipeline]))]
/// pub struct ApiState {
/// // Your additional dependencies
/// pub db_pool: PgPool,
/// pub config: Config,
/// }
///
/// // Use the generated API
/// use api::ApiState;
///
/// let api_state = ApiState {
/// app: Arc::new(RwLock::new(AppState::new())),
/// db_pool: pool,
/// config: cfg,
/// };
///
/// let app = ApiState::router().with_state(api_state);
/// ```
///
/// # Generated Code
///
/// This generates, in scope of the annotated api state:
/// - Response types (`ListResponse`, `EntityResponse`, `OperationResponse`, etc.)
/// - Handler functions for all CRUD operations
/// - Associated methods on the struct:
/// - `ApiState::router()` function returning `Router<S>`
/// - `ApiState::event_middleware(...)` function to listen for CRUD events
/// - OpenAPI annotations providing an OpenAPI doc
///
/// You can create multiple API structs for different purposes (public API, admin API, etc.),
/// each with their own application state.