waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
//! Complete System Example - Manual Implementation (no macros)
//!
//! This example demonstrates error code definitions using the **manual approach**
//! (direct trait implementations without macros).
//!
//! **For the macro-based approach, see:**
//! `waddling-errors-macros/examples/complete_macro_system`
//!
//! ## Key Pattern: Runtime vs Doc-Gen Separation
//!
//! ```bash
//! # Normal runtime (no doc generation)
//! cargo run --example complete_system --features metadata
//!
//! # Documentation generation
//! cargo run --example complete_system --features metadata,doc-gen -- --generate-docs
//! ```
//!
//! ## Features Demonstrated
//!
//! - Manual `ComponentId` and `PrimaryId` trait implementations
//! - Manual `Code<Component, Primary>` constant definitions
//! - Manual documentation registration calls
//! - 6 components (Auth, Database, API, Cache, Queue, Storage, Navigation)
//! - 7 primary categories (Token, Connection, RateLimit, Validation, Permission, Timeout, Data)
//! - All 9 severity types demonstrated
//! - Role-based component locations with explicit visibility
//!
//! ## Project Structure
//!
//! ```
//! complete_system/
//! ├── main.rs              # Entry point with runtime/doc-gen separation
//! ├── sequences.rs         # Sequence definitions
//! ├── primaries/           # Primary category definitions
//! └── components/          # Component definitions
//!     ├── auth.rs          # Manual ComponentId impl
//!     ├── auth_metadata.rs # Manual DiagnosticRuntime creation
//!     └── ...
//! ```

mod components;
mod primaries;
mod sequences;

use components::{api, auth, cache, database, navigation, queue, storage};

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_system --features metadata,doc-gen -- --generate-docs"
            );
            std::process::exit(1);
        }
    }

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

    println!();
    println!("╔═══════════════════════════════════════════════════════════════╗");
    println!("║  🦆 WebApp Backend System - RUNTIME MODE (Manual Approach)    ║");
    println!("║     Using manual trait implementations (no macros)            ║");
    println!("╚═══════════════════════════════════════════════════════════════╝");
    println!();

    // Display registry statistics
    print_registry_statistics();

    // Show actual error code usage
    println!("📋 Using Error Codes at Runtime:\n");

    println!("   ┌─────────────────────────────────────────────────────────────┐");
    println!(
        "   │ Code: {}",
        auth::ERR_TOKEN_MISSING.code()
    );
    println!(
        "   │ Hash: {}",
        auth::ERR_TOKEN_MISSING.hash()
    );
    println!("   └─────────────────────────────────────────────────────────────┘");
    println!();

    // Demonstrate different severities
    println!("📋 Error Code Examples by Severity:\n");

    println!("❌ ERROR:");
    println!("  {} - Missing JWT token", auth::ERR_TOKEN_MISSING.code());
    println!(
        "  {} - DB connection not found",
        database::ERR_CONNECTION_NOTFOUND.code()
    );
    println!(
        "  {} - API unreachable",
        api::ERR_CONNECTION_UNREACHABLE.code()
    );
    println!(
        "  {} - Page not found (404) 🦆",
        navigation::ERR_PAGE_NOT_FOUND.code()
    );
    println!();

    println!("🔥 CRITICAL:");
    println!(
        "  {} - Connection pool exhausted",
        database::ERR_CONNECTION_EXHAUSTED.code()
    );
    println!(
        "  {} - Data corruption detected",
        database::CRIT_DATA_CORRUPTED.code()
    );
    println!(
        "  {} - Storage corruption detected",
        storage::CRIT_DATA_CORRUPTED.code()
    );
    println!();

    println!("🚫 BLOCKED:");
    println!("  {} - Rate limit hit", api::BLOCKED_RATELIMIT.code());
    println!(
        "  {} - Job in progress",
        queue::BLOCKED_TIMEOUT_INPROGRESS.code()
    );
    println!();

    println!("⚠️  WARNING:");
    println!(
        "  {} - Limited permissions",
        auth::WARN_PERMISSION_LIMITED.code()
    );
    println!(
        "  {} - Validation warning",
        api::WARN_VALIDATION_INVALID.code()
    );
    println!("  {} - Cache stale", cache::WARN_DATA_STALE.code());
    println!();

    println!("✅ SUCCESS:");
    println!("  {} - Cache warmed", cache::SUCCESS_WARMED.code());
    println!();

    println!("✔️  COMPLETED:");
    println!("  {} - Job completed", queue::SUCCESS_JOB_COMPLETED.code());
    println!("  {} - Upload completed", storage::COMPLETE_UPLOAD.code());
    println!();

    println!("ℹ️  INFO:");
    println!("  {} - Cache miss", cache::INFO_DATA_MISS.code());
    println!();

    println!("🔍 TRACE:");
    println!("  {} - Debug trace", storage::TRACE_OPERATION.code());
    println!();

    // Demonstrate sequence convention compliance
    println!("📏 Sequence Convention Examples:\n");
    println!("  .001 (MISSING):    {}", auth::ERR_TOKEN_MISSING.code());
    println!("  .003 (INVALID):    {}", auth::ERR_TOKEN_INVALID.code());
    println!("  .007 (DUPLICATE):  {}", api::BLOCKED_RATELIMIT.code());
    println!(
        "  .008 (DENIED):     {}",
        auth::ERR_PERMISSION_DENIED.code()
    );
    println!("  .014 (CANCELLED):  {}", queue::ERR_JOB_CANCELLED.code());
    println!(
        "  .015 (INPROGRESS): {}",
        queue::BLOCKED_TIMEOUT_INPROGRESS.code()
    );
    println!("  .017 (TIMEOUT):    {}", auth::ERR_TOKEN_EXPIRED.code());
    println!("  .018 (STALE):      {}", cache::WARN_DATA_STALE.code());
    println!(
        "  .021 (NOTFOUND):   {} 🦆 ← 404 Page Not Found!",
        navigation::ERR_PAGE_NOT_FOUND.code()
    );
    println!(
        "  .022 (EXISTS):     {}",
        storage::ERR_DATA_ALREADYEXISTS.code()
    );
    println!(
        "  .023 (CONFLICT):   {}",
        database::ERR_DATA_CONFLICT.code()
    );
    println!(
        "  .025 (CORRUPTED):  {}",
        database::CRIT_DATA_CORRUPTED.code()
    );
    println!(
        "  .026 (EXHAUSTED):  {}",
        database::ERR_CONNECTION_EXHAUSTED.code()
    );
    println!(
        "  .027 (UNAVAIL):    {}",
        api::ERR_CONNECTION_UNAVAILABLE.code()
    );
    println!(
        "  .028 (UNREACH):    {}",
        api::ERR_CONNECTION_UNREACHABLE.code()
    );
    println!("  .999 (COMPLETE):   {}", cache::SUCCESS_WARMED.code());
    println!();

    #[cfg(feature = "runtime-hash")]
    {
        println!("🔐 Hash Feature Demo:");
        println!(
            "  {}{}",
            auth::ERR_TOKEN_MISSING.code(),
            auth::ERR_TOKEN_MISSING.hash()
        );
        println!(
            "  {}{}",
            database::CRIT_DATA_CORRUPTED.code(),
            database::CRIT_DATA_CORRUPTED.hash()
        );
        println!();
    }

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

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

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

/// Print registry statistics
///
/// Demonstrates registry introspection APIs:
/// - `registry::statistics()` - Get counts of registered items
/// - Shows auto-registration is working
/// - Useful for debugging and verification
#[cfg(feature = "metadata")]
fn print_registry_statistics() {
    use waddling_errors::registry;

    println!("📊 Registry Statistics (Auto-Registration)\n");

    let (diag_count, comp_count, prim_count, seq_count, _loc_count) = registry::statistics();

    println!("   Diagnostics: {}", diag_count);
    println!("   Components:  {}", comp_count);
    println!("   Primaries:   {}", prim_count);
    println!("   Sequences:   {}", seq_count);
    println!();
    println!("   ℹ️  These are auto-registered via ComponentId/PrimaryId traits");
    println!("   ℹ️  Available in no_std environments (stored in static arrays)");
    println!();
}

#[cfg(not(feature = "metadata"))]
fn print_registry_statistics() {
    println!("📊 Registry Statistics\n");
    println!("   ⚠️  Requires 'metadata' feature\n");
}

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

    println!();
    println!("╔═══════════════════════════════════════════════════════════════╗");
    println!("║  📚 WebApp Backend System - DOC GENERATION MODE               ║");
    println!("║     Manual approach (no macros)                               ║");
    println!("╚═══════════════════════════════════════════════════════════════╝");
    println!();

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

    // Manual registration (this is what macros automate)
    println!("📝 Registering metadata (manual approach)...");
    sequences::register_sequences(&mut registry);
    primaries::register_primaries(&mut registry);
    components::register_all_components(&mut registry);
    components::register_all_errors(&mut registry);

    println!("{} sequences", registry.sequences().len());
    println!("{} primaries", registry.primaries().len());
    println!("{} components", registry.components().len());
    println!("{} errors", registry.errors().len());
    println!();

    // Validate see_also references
    println!("🔍 Validating documentation links...");
    let broken_links = validate_see_also_links(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);
        }
    }
    println!();

    // Create HTML renderer with duck logo 🦆
    let duck_logo = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ctext y='.9em' font-size='90'%3E🦆%3C/text%3E%3C/svg%3E";
    let customization = HtmlCustomization::new()
        .with_logo(duck_logo, "Waddling Errors")
        .with_accent_color("#f59e0b", "#fbbf24");

    let html_renderer = HtmlRenderer::with_customization(customization);

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

    match registry.render_all_roles(
        vec![Box::new(html_renderer), Box::new(JsonRenderer)],
        "target/doc",
    ) {
        Ok(_) => {
            println!();
            println!("╔═══════════════════════════════════════════════════════════════╗");
            println!("║  ✅ Documentation Generated Successfully                      ║");
            println!("╠═══════════════════════════════════════════════════════════════╣");
            println!("║  📘 target/doc/WebApp_Backend_System-pub.html                 ║");
            println!("║  👨‍💻 target/doc/WebApp_Backend_System-dev.html                 ║");
            println!("║  🔒 target/doc/WebApp_Backend_System-int.html                 ║");
            println!("║  📄 target/doc/WebApp_Backend_System-pub.json                 ║");
            println!("║  📄 target/doc/WebApp_Backend_System-dev.json                 ║");
            println!("║  📄 target/doc/WebApp_Backend_System-int.json                 ║");
            println!("╚═══════════════════════════════════════════════════════════════╝");
            println!();
        }
        Err(e) => {
            eprintln!("❌ Documentation 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.