1
use supp_macro::command;
2

            
3
#[derive(Debug)]
4
pub enum CmdError {
5
    Args(String),
6
}
7

            
8
impl std::fmt::Display for CmdError {
9
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10
        match self {
11
            CmdError::Args(msg) => write!(f, "Argument error: {}", msg),
12
        }
13
    }
14
}
15

            
16
impl std::error::Error for CmdError {}
17

            
18
#[derive(Debug)]
19
pub enum CmdResult {
20
    Success(String),
21
    Value(i64),
22
}
23

            
24
// Define commands using the progressive types approach
25
command! {
26
    CreateUser {
27
        #[required]
28
        username: String,
29
        #[required]
30
        email: String,
31
        #[optional]
32
        is_admin: bool,
33
    } => {
34
        let admin_status = is_admin.unwrap_or(false);
35
        Ok(Some(CmdResult::Success(format!(
36
            "Created user {} with email {} (admin: {})",
37
            username, email, admin_status
38
        ))))
39
    }
40
}
41

            
42
command! {
43
    GetVersion {
44
    } => {
45
        Ok(Some(CmdResult::Success("v1.0.0".to_string())))
46
    }
47
}
48

            
49
command! {
50
    Calculate {
51
        #[required]
52
        a: i64,
53
        #[required]
54
        b: i64,
55
    } => {
56
        Ok(Some(CmdResult::Value(a + b)))
57
    }
58
}
59

            
60
#[tokio::main]
61
async fn main() -> Result<(), Box<dyn std::error::Error>> {
62
    println!("šŸš€ Progressive Types Command Demo");
63
    println!("===================================");
64

            
65
    // āœ… SIMPLE INTERFACE - No Args types visible to users!
66

            
67
    println!("\n1. Simple command with no arguments:");
68
    let result = GetVersion::new().run().await?;
69
    println!("   Result: {:?}", result);
70

            
71
    println!("\n2. Command with required arguments (compile-time validated):");
72
    let result = Calculate::new()
73
        .a(10) // āœ… i64 type enforced at compile time
74
        .b(20) // āœ… i64 type enforced at compile time
75
        .run() // āœ… Only available when all required fields set
76
        .await?;
77
    println!("   Result: {:?}", result);
78

            
79
    println!("\n3. Command with mixed required and optional arguments:");
80
    let result = CreateUser::new()
81
        .username("alice".to_string()) // āœ… Required
82
        .email("alice@example.com".to_string()) // āœ… Required
83
        .is_admin(true) // āœ… Optional
84
        .run()
85
        .await?;
86
    println!("   Result: {:?}", result);
87

            
88
    println!("\n4. Same command with minimal arguments (optional fields omitted):");
89
    let result = CreateUser::new()
90
        .username("bob".to_string()) // āœ… Required
91
        .email("bob@example.com".to_string()) // āœ… Required
92
        // is_admin omitted - will be None/false
93
        .run()
94
        .await?;
95
    println!("   Result: {:?}", result);
96

            
97
    println!("\nāœ… Features demonstrated:");
98
    println!("   - Zero Args type naming (users never see *Args structs)");
99
    println!("   - Compile-time type validation (wrong types = compile error)");
100
    println!("   - Compile-time required field validation (missing fields = compile error)");
101
    println!("   - Zero runtime checks (direct field access, no unwrap())");
102
    println!("   - Clean, intuitive interface (Command::new().field().run())");
103

            
104
    // Uncomment these to see compile-time errors:
105

            
106
    // āŒ This would NOT compile - missing required field:
107
    // let result = CreateUser::new()
108
    //     .username("incomplete".to_string())
109
    //     .run()  // ERROR: no method named `run` found
110
    //     .await?;
111

            
112
    // āŒ This would NOT compile - wrong type:
113
    // let result = Calculate::new()
114
    //     .a("not_a_number")  // ERROR: expected `i64`, found `&str`
115
    //     .b(20)
116
    //     .run()
117
    //     .await?;
118

            
119
    // āŒ This would NOT compile - method doesn't exist:
120
    // let result = GetVersion::new()
121
    //     .invalid_method("test")  // ERROR: no method named `invalid_method`
122
    //     .run()
123
    //     .await?;
124

            
125
    Ok(())
126
}