waddling-errors-macros 0.7.3

Procedural macros for structured error codes with compile-time validation and taxonomy enforcement
Documentation
//! Complete System Example - Macro-Based Version
//!
//! This example demonstrates a realistic web application backend using
//! waddling-errors-macros for concise, maintainable error definitions.
//!
//! **Key Pattern:** Doc generation is SEPARATED from normal runtime via a flag.
//!
//! ## Features Demonstrated
//! - `component!` macro for component definitions with metadata
//! - `primary!` macro for primary category enums with documentation
//! - `diag!` macro with `<formats>` for auto-registration
//! - Role-based documentation ('Pub, 'Dev, 'Int markers)
//! - Automatic diagnostic registration (no manual calls needed)
//! - **Runtime vs Doc-Gen separation** via `--generate-docs` flag
//!
//! ## Running (Normal - no doc generation)
//!
//! ```bash
//! cargo run --example complete_macro_system --features metadata,auto-register
//! ```
//!
//! ## Running (Doc Generation)
//!
//! ```bash
//! cargo run --example complete_macro_system --features metadata,auto-register,doc-gen -- --generate-docs
//! ```
//!
//! ## Key Benefits
//!
//! **Lines of code:** ~70% reduction per component
//! **Boilerplate:** Zero manual trait implementations
//! **Registration:** Automatic via `<formats>` specification
//! **Maintainability:** Unified DSL syntax across all macros
//! **Separation:** Doc-gen code NOT compiled into production binary

pub mod components;
pub mod primaries;
pub mod sequences;

use waddling_errors::registry;
use waddling_errors_macros::setup;

// Import error constants for runtime demonstration
use components::auth::{E_AUTH_TOKEN_EXPIRED, E_AUTH_TOKEN_MISSING};
use components::cache::S_CACHE_DATA_WARMED;
use components::database::C_DB_CONNECTION_EXHAUSTED;

// Set up path resolution for diag! macro to find components, primaries, and sequences.
// This creates __wd_paths module with re-exports.
setup! {
    components = crate::components,
    primaries = crate::primaries,
    sequences = crate::sequences,
}

fn main() {
    // Check for --generate-docs flag FIRST
    let args: Vec<String> = std::env::args().collect();
    if args.iter().any(|a| a == "--generate-docs") {
        #[cfg(feature = "doc-gen")]
        {
            generate_documentation();
            return;
        }
        #[cfg(not(feature = "doc-gen"))]
        {
            eprintln!("❌ Error: doc-gen feature not enabled");
            eprintln!(
                "   Run with: cargo run --example complete_macro_system --features metadata,auto-register,doc-gen -- --generate-docs"
            );
            std::process::exit(1);
        }
    }

    // ═══════════════════════════════════════════════════════════════════
    // NORMAL RUNTIME MODE
    // ═══════════════════════════════════════════════════════════════════

    println!();
    println!("╔═══════════════════════════════════════════════════════════════╗");
    println!("║  🦆 WebApp Backend System - RUNTIME MODE                      ║");
    println!("║     Using waddling-errors-macros                              ║");
    println!("╚═══════════════════════════════════════════════════════════════╝");
    println!();

    // ─────────────────────────────────────────────────────────────────────
    // Demonstrate ACTUAL error code usage with real values
    // ─────────────────────────────────────────────────────────────────────

    println!("📋 Using Error Codes at Runtime:\n");

    // Show actual error code values
    println!("   ┌─────────────────────────────────────────────────────────────┐");
    println!(
        "   │ Code: {}",
        E_AUTH_TOKEN_MISSING.code
    );
    println!(
        "   │ Hash: {}",
        E_AUTH_TOKEN_MISSING.hash
    );
    println!("   │ Message: {}", E_AUTH_TOKEN_MISSING.message);
    println!("   └─────────────────────────────────────────────────────────────┘");
    println!();

    // Simulate a request flow with actual error messages
    println!("🔄 Simulating API Request Flow:\n");

    println!("   1️⃣  Checking authentication...");
    println!("      → Token found in header");
    println!();

    println!("   2️⃣  Validating token...");
    println!("      ⚠️  Token expired!");
    println!(
        "      Code: {} | Hash: {}",
        E_AUTH_TOKEN_EXPIRED.code, E_AUTH_TOKEN_EXPIRED.hash
    );
    println!("      Message: \"{}\"", E_AUTH_TOKEN_EXPIRED.message);
    println!();

    println!("   3️⃣  After refresh, checking permissions...");
    println!("      → User has required permissions");
    println!();

    println!("   4️⃣  Loading from cache...");

    // Show a success case using the Success severity
    println!(
        "{} | Hash: {}",
        S_CACHE_DATA_WARMED.code, S_CACHE_DATA_WARMED.hash
    );
    println!("      Message: \"{}\"", S_CACHE_DATA_WARMED.message);
    println!();

    println!("   5️⃣  Database health check...");
    println!("      Pool status: 48/50 connections available");
    println!(
        "      (If exhausted, would trigger: {} [{}])",
        C_DB_CONNECTION_EXHAUSTED.code, C_DB_CONNECTION_EXHAUSTED.hash
    );
    println!();

    // ─────────────────────────────────────────────────────────────────────
    // Show registry statistics
    // ─────────────────────────────────────────────────────────────────────

    #[cfg(feature = "auto-register")]
    {
        let (diag_count, comp_count, prim_count, seq_count, loc_count) = registry::statistics();

        println!("═══════════════════════════════════════════════════════════════");
        println!();
        println!("📊 System Statistics (auto-registered at startup):\n");
        println!(
            "   Diagnostics: {:>3}  │  Components: {:>2}",
            diag_count, comp_count
        );
        println!(
            "   Primaries:   {:>3}  │  Sequences:  {:>2}",
            prim_count, seq_count
        );
        println!("   Locations:   {:>3}", loc_count);
        println!();
    }

    // ─────────────────────────────────────────────────────────────────────
    // Show how to generate docs (hint for users)
    // ─────────────────────────────────────────────────────────────────────

    println!("═══════════════════════════════════════════════════════════════");
    println!();
    println!("📚 To Generate Documentation (SEPARATE MODE):");
    println!();
    println!("   cargo run --example complete_macro_system \\");
    println!("       --features metadata,auto-register,doc-gen -- --generate-docs");
    println!();
    println!("   This compiles a DIFFERENT binary with doc-gen code included.");
    println!();

    // ─────────────────────────────────────────────────────────────────────
    // Final success message using actual Success severity
    // ─────────────────────────────────────────────────────────────────────

    println!("╔═══════════════════════════════════════════════════════════════╗");
    println!(
        "║  ✅ {} - System Running Successfully         ║",
        S_CACHE_DATA_WARMED.code
    );
    println!("╚═══════════════════════════════════════════════════════════════╝");
    println!();
}

#[cfg(feature = "doc-gen")]
fn generate_documentation() {
    use waddling_errors::doc_generator::{
        DocRegistry, HtmlRenderer, JsonRenderer, validate_see_also_links,
    };

    println!();
    println!("╔═══════════════════════════════════════════════════════════════╗");
    println!("║  📚 WebApp Backend System - DOC GENERATION MODE               ║");
    println!("║     Generating HTML & JSON documentation                      ║");
    println!("╚═══════════════════════════════════════════════════════════════╝");
    println!();

    let mut doc_registry = DocRegistry::new("WebApp Backend (Macros)", env!("CARGO_PKG_VERSION"));

    // Auto-registration magic: bulk-register all components, primaries, diagnostics, sequences,
    // AND component locations (from component_location! macro)
    #[cfg(feature = "auto-register")]
    {
        registry::register_all_with_doc_gen(&mut doc_registry);

        let (
            diagnostics_count,
            components_count,
            primaries_count,
            sequences_count,
            locations_count,
        ) = registry::statistics();
        println!("📊 Registered from auto-registration:\n");
        println!("{} diagnostics", diagnostics_count);
        println!("{} components", components_count);
        println!("{} primaries", primaries_count);
        println!("{} sequences", sequences_count);
        println!("{} component locations", locations_count);
    }

    #[cfg(not(feature = "auto-register"))]
    {
        eprintln!("❌ auto-register feature required for doc generation");
        std::process::exit(1);
    }

    // Validate links
    println!();
    println!("🔍 Validating documentation links...");
    let broken_links = validate_see_also_links(doc_registry.errors());

    if broken_links.is_empty() {
        println!("   ✓ All see_also references valid");
    } else {
        println!("   ⚠️  Found {} broken reference(s)", broken_links.len());
        for link in broken_links.iter().take(3) {
            println!("      {} -> {} (not found)", link.from_code, link.to_code);
        }
    }

    // Generate documentation files
    println!();
    println!("📝 Generating documentation files...");

    match doc_registry.render_all_roles(
        vec![Box::new(HtmlRenderer::new()), Box::new(JsonRenderer)],
        "target/doc",
    ) {
        Ok(_) => {
            println!();
            println!("╔═══════════════════════════════════════════════════════════════╗");
            println!("║  ✅ Documentation Generated Successfully                      ║");
            println!("╠═══════════════════════════════════════════════════════════════╣");
            println!("║  📘 target/doc/WebApp_Backend_(Macros)-pub.html               ║");
            println!("║  👨‍💻 target/doc/WebApp_Backend_(Macros)-dev.html               ║");
            println!("║  🔒 target/doc/WebApp_Backend_(Macros)-int.html               ║");
            println!("║  📄 target/doc/WebApp_Backend_(Macros)-pub.json               ║");
            println!("║  📄 target/doc/WebApp_Backend_(Macros)-dev.json               ║");
            println!("║  📄 target/doc/WebApp_Backend_(Macros)-int.json               ║");
            println!("╚═══════════════════════════════════════════════════════════════╝");
            println!();
        }
        Err(e) => {
            eprintln!("❌ Generation failed: {}", e);
            std::process::exit(1);
        }
    }
}

// Note: No #[cfg(not(feature = "doc-gen"))] stub needed!
// The main() function handles the case where doc-gen is not enabled
// but --generate-docs flag is passed.