lifecycle_hooks_demo/
lifecycle_hooks_demo.rs1use flag_rs::{CommandBuilder, Flag, FlagType};
7use std::sync::atomic::{AtomicU32, Ordering};
8
9static COUNTER: AtomicU32 = AtomicU32::new(0);
11
12fn log_hook(name: &str) {
13 let count = COUNTER.fetch_add(1, Ordering::SeqCst);
14 println!("[{:02}] {}", count + 1, name);
15}
16
17fn main() {
18 let app = CommandBuilder::new("lifecycle-demo")
19 .short("Demonstrates lifecycle hooks")
20 .long("This example shows how lifecycle hooks execute in the proper order")
21 .flag(
22 Flag::new("verbose")
23 .short('v')
24 .usage("Enable verbose output")
25 .value_type(FlagType::Bool),
26 )
27 .persistent_pre_run(|ctx| {
29 log_hook("Root PersistentPreRun");
30 if ctx.flag("verbose").is_some() {
31 println!(" -> Verbose mode enabled globally");
32 }
33 Ok(())
34 })
35 .persistent_post_run(|ctx| {
36 log_hook("Root PersistentPostRun");
37 if ctx.flag("verbose").is_some() {
38 println!(" -> Cleaning up verbose logging");
39 }
40 Ok(())
41 })
42 .subcommand(
43 CommandBuilder::new("server")
44 .short("Server management commands")
45 .persistent_pre_run(|_ctx| {
46 log_hook("Server PersistentPreRun");
47 println!(" -> Initializing server module");
48 Ok(())
49 })
50 .persistent_post_run(|_ctx| {
51 log_hook("Server PersistentPostRun");
52 println!(" -> Cleaning up server module");
53 Ok(())
54 })
55 .subcommand(
56 CommandBuilder::new("start")
57 .short("Start the server")
58 .flag(
59 Flag::new("port")
60 .short('p')
61 .usage("Port to listen on")
62 .value_type(FlagType::Int),
63 )
64 .pre_run(|ctx| {
65 log_hook("Start PreRun");
66 let port = ctx
67 .flag("port")
68 .and_then(|s| s.parse::<u16>().ok())
69 .unwrap_or(8080);
70 println!(" -> Validating port {}", port);
71 Ok(())
72 })
73 .run(|ctx| {
74 log_hook("Start Run");
75 let port = ctx
76 .flag("port")
77 .and_then(|s| s.parse::<u16>().ok())
78 .unwrap_or(8080);
79 println!(" -> Starting server on port {}", port);
80 Ok(())
81 })
82 .post_run(|_ctx| {
83 log_hook("Start PostRun");
84 println!(" -> Server started successfully");
85 Ok(())
86 })
87 .build(),
88 )
89 .subcommand(
90 CommandBuilder::new("stop")
91 .short("Stop the server")
92 .pre_run(|_ctx| {
93 log_hook("Stop PreRun");
94 println!(" -> Checking if server is running");
95 Ok(())
96 })
97 .run(|_ctx| {
98 log_hook("Stop Run");
99 println!(" -> Stopping server");
100 Ok(())
101 })
102 .post_run(|_ctx| {
103 log_hook("Stop PostRun");
104 println!(" -> Server stopped");
105 Ok(())
106 })
107 .build(),
108 )
109 .build(),
110 )
111 .subcommand(
112 CommandBuilder::new("database")
113 .short("Database management commands")
114 .persistent_pre_run(|_ctx| {
115 log_hook("Database PersistentPreRun");
116 println!(" -> Connecting to database");
117 Ok(())
118 })
119 .persistent_post_run(|_ctx| {
120 log_hook("Database PersistentPostRun");
121 println!(" -> Closing database connection");
122 Ok(())
123 })
124 .subcommand(
125 CommandBuilder::new("migrate")
126 .short("Run database migrations")
127 .pre_run(|_ctx| {
128 log_hook("Migrate PreRun");
129 println!(" -> Checking migration status");
130 Ok(())
131 })
132 .run(|_ctx| {
133 log_hook("Migrate Run");
134 println!(" -> Running migrations");
135 Ok(())
136 })
137 .post_run(|_ctx| {
138 log_hook("Migrate PostRun");
139 println!(" -> Migrations completed");
140 Ok(())
141 })
142 .build(),
143 )
144 .build(),
145 )
146 .build();
147
148 println!("=== Lifecycle Hooks Demo ===\n");
149 println!("This demo shows the execution order of lifecycle hooks.");
150 println!("Try these commands to see different hook patterns:\n");
151 println!(
152 "1. {} server start",
153 std::env::args().next().unwrap_or_default()
154 );
155 println!(
156 "2. {} -v server start -p 3000",
157 std::env::args().next().unwrap_or_default()
158 );
159 println!(
160 "3. {} database migrate",
161 std::env::args().next().unwrap_or_default()
162 );
163 println!("\n---\n");
164
165 COUNTER.store(0, Ordering::SeqCst);
167
168 let args: Vec<String> = std::env::args().skip(1).collect();
169 if let Err(e) = app.execute(args) {
170 eprintln!("Error: {}", e);
171 std::process::exit(1);
172 }
173
174 println!("\n=== Hook Execution Summary ===");
175 println!("Total hooks executed: {}", COUNTER.load(Ordering::SeqCst));
176 println!("\nExecution order:");
177 println!("1. Parent PersistentPreRun (root → child)");
178 println!("2. Command PreRun");
179 println!("3. Command Run");
180 println!("4. Command PostRun");
181 println!("5. Parent PersistentPostRun (child → root)");
182}