lupa 0.1.1

Interactive object inspector for Rust — web UI + TUI + snapshot diffing
Documentation
//! # Basic example for `lupa`
//!
//! This example demonstrates the simplest possible usage of the `lupa` inspector.
//! It creates a `User` struct, takes several snapshots, mutates the data,
//! and finally shows a diff between the initial and final state.
//!
//! ## Run
//! ```bash
//! cargo run --example basic
//! ```
//!
//! Then open [http://localhost:7777](http://localhost:7777) in your browser.
//! The inspector will show:
//! - Three snapshots (initial, after activity, after promotion)
//! - One diff (initial vs final state)
//!
//! Press `Ctrl+C` in the terminal to stop the web server.

use lupa::{inspect, snapshot, snapshot_diff, RunMode};
use std::collections::HashMap;

// ---------- Data model ----------

/// A rich user struct to demonstrate snapshot diffing on various field types.
#[derive(Debug, Clone)]
struct User {
    id: u64,
    name: String,
    email: String,
    age: u32,
    role: Role,
    address: Address,
    tags: Vec<String>,
    scores: HashMap<String, f32>,
    active: bool,
}

#[derive(Debug, Clone)]
enum Role {
    Guest,
    Moderator,
    Admin { since: String },
}

#[derive(Debug, Clone)]
struct Address {
    city: String,
    country: String,
    zip: String,
}

impl User {
    /// Creates a new user with default values.
    fn new(id: u64, name: &str, email: &str) -> Self {
        Self {
            id,
            name: name.into(),
            email: email.into(),
            age: 28,
            role: Role::Guest,
            address: Address {
                city: "Berlin".into(),
                country: "DE".into(),
                zip: "10115".into(),
            },
            tags: vec!["newcomer".into()],
            scores: HashMap::from([
                ("reputation".into(), 10.0),
                ("activity".into(), 0.0),
            ]),
            active: true,
        }
    }

    /// Promotes the user to admin, changing role, tags and reputation.
    fn promote_to_admin(&mut self) {
        self.role = Role::Admin {
            since: "2024-06-01".into(),
        };
        self.tags.push("admin".into());
        self.tags.retain(|t| t != "newcomer");
        *self.scores.entry("reputation".into()).or_default() += 500.0;
    }

    /// Records user activity: increases activity score and increments age.
    fn record_activity(&mut self, points: f32) {
        *self.scores.entry("activity".into()).or_default() += points;
        self.age += 1;
    }
}

// ---------- Main ----------

fn main() {
    let mut user = User::new(42, "Alice", "alice@example.com");

    // 1. First snapshot – the freshly created user.
    println!("[1/4] Inspecting freshly created user…");
    inspect!(user);

    // Capture a "before" snapshot for later diffing.
    let snapshot_before = snapshot!(user);

    // 2. Record some activity and take another snapshot.
    println!("[2/4] Recording activity…");
    user.record_activity(75.5);
    inspect!(user);

    // 3. Promote to admin, change address, and take a third snapshot.
    println!("[3/4] Promoting to Admin…");
    user.promote_to_admin();
    user.address.city = "Munich".into();
    user.address.zip = "80331".into();
    inspect!(user);

    // 4. Compute and send a diff between the initial state and the final one.
    println!("[4/4] Diffing initial state vs current…");
    snapshot_diff!(snapshot_before, user);

    println!("\n✅ Done! Check the browser. Press Ctrl+C to exit.");
    // Start the web server and block until Ctrl+C.
    lupa::run_mode(RunMode::Web).unwrap();
}