vika_cli/commands/
update.rs1use crate::config::loader::load_config;
2use crate::config::validator::validate_config;
3use crate::error::Result;
4use crate::generator::api_client::generate_api_client_with_registry;
5use crate::generator::swagger_parser::{fetch_and_parse_spec, filter_common_schemas};
6use crate::generator::ts_typings::generate_typings_with_registry;
7use crate::generator::writer::{write_api_client, write_schemas};
8use crate::generator::zod_schema::generate_zod_schemas_with_registry;
9use colored::*;
10use std::path::PathBuf;
11
12pub async fn run() -> Result<()> {
13 println!("{}", "🔄 Updating generated code...".bright_cyan());
14 println!();
15
16 let config = load_config()?;
18 validate_config(&config)?;
19
20 use crate::error::GenerationError;
21
22 let spec_path = config.spec_path.ok_or(GenerationError::SpecPathRequired)?;
24
25 let selected_modules = if config.modules.selected.is_empty() {
27 return Err(GenerationError::NoModulesSelected.into());
28 } else {
29 config.modules.selected.clone()
30 };
31
32 println!(
33 "{}",
34 format!("📥 Fetching spec from: {}", spec_path).bright_blue()
35 );
36 let parsed = fetch_and_parse_spec(&spec_path).await?;
37 println!(
38 "{}",
39 format!("✅ Parsed spec with {} modules", parsed.modules.len()).green()
40 );
41 println!();
42 println!(
43 "{}",
44 format!(
45 "📦 Updating {} module(s): {}",
46 selected_modules.len(),
47 selected_modules.join(", ")
48 )
49 .bright_green()
50 );
51 println!();
52
53 let (filtered_module_schemas, common_schemas) =
55 filter_common_schemas(&parsed.module_schemas, &selected_modules);
56
57 let schemas_dir = PathBuf::from(&config.schemas.output);
59 let apis_dir = PathBuf::from(&config.apis.output);
60
61 let mut total_files = 0;
62 let mut module_summary: Vec<(String, usize)> = Vec::new();
63
64 if !common_schemas.is_empty() {
66 println!("{}", "🔨 Regenerating common schemas...".bright_cyan());
67
68 let mut shared_enum_registry = std::collections::HashMap::new();
70
71 let common_types = generate_typings_with_registry(
73 &parsed.openapi,
74 &parsed.schemas,
75 &common_schemas,
76 &mut shared_enum_registry,
77 &common_schemas,
78 )?;
79
80 let common_zod_schemas = generate_zod_schemas_with_registry(
82 &parsed.openapi,
83 &parsed.schemas,
84 &common_schemas,
85 &mut shared_enum_registry,
86 &common_schemas,
87 )?;
88
89 let common_files =
91 write_schemas(&schemas_dir, "common", &common_types, &common_zod_schemas)?;
92 total_files += common_files.len();
93 module_summary.push(("common".to_string(), common_files.len()));
94 }
95
96 for module in &selected_modules {
97 println!(
98 "{}",
99 format!("🔨 Regenerating code for module: {}", module).bright_cyan()
100 );
101
102 let operations = parsed
104 .operations_by_tag
105 .get(module)
106 .cloned()
107 .unwrap_or_default();
108
109 if operations.is_empty() {
110 println!(
111 "{}",
112 format!("⚠️ No operations found for module: {}", module).yellow()
113 );
114 continue;
115 }
116
117 let module_schema_names = filtered_module_schemas
119 .get(module)
120 .cloned()
121 .unwrap_or_default();
122
123 let mut shared_enum_registry = std::collections::HashMap::new();
125
126 let types = if !module_schema_names.is_empty() {
128 generate_typings_with_registry(
129 &parsed.openapi,
130 &parsed.schemas,
131 &module_schema_names,
132 &mut shared_enum_registry,
133 &common_schemas,
134 )?
135 } else {
136 Vec::new()
137 };
138
139 let zod_schemas = if !module_schema_names.is_empty() {
141 generate_zod_schemas_with_registry(
142 &parsed.openapi,
143 &parsed.schemas,
144 &module_schema_names,
145 &mut shared_enum_registry,
146 &common_schemas,
147 )?
148 } else {
149 Vec::new()
150 };
151
152 let api_result = generate_api_client_with_registry(
154 &parsed.openapi,
155 &operations,
156 module,
157 &common_schemas,
158 &mut shared_enum_registry,
159 )?;
160
161 let mut all_types = types;
163 all_types.extend(api_result.response_types);
164
165 let schema_files = write_schemas(&schemas_dir, module, &all_types, &zod_schemas)?;
167 total_files += schema_files.len();
168
169 let api_files = write_api_client(&apis_dir, module, &api_result.functions)?;
171 total_files += api_files.len();
172
173 let module_file_count = schema_files.len() + api_files.len();
174 module_summary.push((module.clone(), module_file_count));
175 println!(
176 "{}",
177 format!(
178 "✅ Regenerated {} files for module: {}",
179 module_file_count, module
180 )
181 .green()
182 );
183 }
184
185 println!();
186 println!(
187 "{}",
188 format!("✨ Successfully updated {} files!", total_files).bright_green()
189 );
190 println!();
191 println!("{}", "Updated files:".bright_cyan());
192 println!(" 📁 Schemas: {}", config.schemas.output);
193 println!(" 📁 APIs: {}", config.apis.output);
194 println!();
195 if !module_summary.is_empty() {
196 println!("{}", "Module breakdown:".bright_cyan());
197 for (module, count) in &module_summary {
198 println!(" • {}: {} files", module, count);
199 }
200 }
201
202 Ok(())
203}