stately 0.5.0

Type-safe state management with entity relationships and CRUD operations
Documentation
#![allow(clippy::needless_for_each)]
#![allow(unused_crate_dependencies)]
//! # Generated Code Examples - Demo
//!
//! > **All code here is automatically generated from the example in
//! > `stately/examples/doc_expand.rs`. It is
//! > for illustration only to show what gets generated in your actual crate.**
//!
//! This module demonstrates the code generated by stately's procedural macros.
//! All code shown here is automatically generated when you use the `#[stately::state]` and
//! `#[stately::axum_api]` macros in your crate.
//!
//! **Note:** This module is only included when building documentation (`#[cfg(doc)]`).
//! These types are for illustration and show what gets generated in your actual crate.
//!
//! ## What Gets Generated
//!
//! When you use `#[stately::state]` on a struct, the macro generates:
//!
//! - **[`StateEntry`] enum** - Discriminator for entity types with string conversion
//! - **[`Entity`] enum** - Type-erased wrapper for all entity types
//! - **[`ForeignEntity`] trait** - Impl on external types (when using `#[collection(foreign)]`)
//! - **Wrapper types** - When using `variant = "..."` (e.g., [`ArchivedPipeline`], [`JsonConfig`])
//! - **[`State`] implementation** - With CRUD methods like `create_entity`, `update_entity`, etc.
//! - **[`link_aliases`] module** - Type aliases like `PipelineLink = Link<Pipeline>`
//!
//! When you additionally use `#[stately::axum_api(State)]`, the macro also generates:
//!
//! - **[`ApiState`] implementation** - With handler methods and `router()`
//! - **[`ResponseEvent`] enum** - Events emitted after CRUD operations
//! - **Request/Response types** - For all API endpoints
//! - **`OpenAPI` documentation** - When using the `openapi` parameter
//!
//! ## Source Example
//!
//! The code below is generated from the example at `crates/stately/examples/doc_expand.rs`:
//!
//! ```rust,ignore
//! #[stately::entity]
//! #[derive(Clone, serde::Serialize, serde::Deserialize)]
//! pub struct Pipeline {
//!     pub name: String,
//!     pub source: Link<Source>,
//! }
//!
//! #[stately::state(openapi)]
//! pub struct State {
//!     pipelines: Pipeline,
//!     sources: Source,
//!
//!     // Variant for multiple uses of same type
//!     #[collection(variant = "ArchivedPipeline")]
//!     archived: Pipeline,
//!
//!     // Custom collection type
//!     #[collection(SinkCollection)]
//!     sinks: Sink,
//!
//!     // Foreign type support
//!     #[collection(foreign, variant = "JsonConfig")]
//!     configs: serde_json::Value,
//! }
//!
//! #[stately::axum_api(State, openapi)]
//! pub struct ApiState {}
//! ```
// utoipa bug...
use stately::prelude::*;

// Regular entities
#[stately::entity]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct Pipeline {
    pub name:   String,
    pub source: Link<Source>,
}

#[stately::entity]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct Source {
    pub name: String,
    pub url:  String,
}

#[stately::entity]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct Sink {
    pub name:        String,
    pub destination: String,
}

// Custom collection type
type SinkCollection = Collection<Sink>;

// State with all features demonstrated
#[stately::state(openapi)]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct State {
    // Regular collections (implicit Collection<T>)
    pipelines: Pipeline,
    sources:   Source,

    // Variant wrapper - multiple uses of same type
    #[collection(variant = "ArchivedPipeline")]
    archived: Pipeline,

    // Custom collection type
    #[collection(SinkCollection)]
    sinks: Sink,

    // Foreign type
    #[collection(foreign, variant = "JsonConfig")]
    configs: serde_json::Value,
}

// Implement ForeignEntity for the external type
impl ForeignEntity for serde_json::Value {
    fn name(&self) -> &str { self.get("name").and_then(|v| v.as_str()).unwrap_or("unnamed") }

    fn description(&self) -> Option<&str> { self.get("description").and_then(|v| v.as_str()) }
}

// Axum API (when feature is enabled)

#[stately::axum_api(State, openapi(components = [
    link_aliases::PipelineLink,
    link_aliases::SourceLink,
    link_aliases::ArchivedPipelineLink,
    link_aliases::SinkLink,
    link_aliases::JsonConfigLink,
]))]
pub struct ApiState {}

fn main() {
    let _state = State::new();
    println!("State created with {} collections", 5);
}