vika_cli/generator/hooks/
context.rs1use crate::generator::utils::sanitize_module_name;
2use crate::templates::context::Parameter;
3use serde::Serialize;
4
5#[derive(Debug, Clone, Serialize)]
7pub struct HookContext {
8 pub hook_name: String,
9 pub key_name: String,
10 pub operation_id: String,
11 pub http_method: String,
12 pub path: String,
13 pub path_params: Vec<Parameter>,
14 pub query_params: Vec<Parameter>,
15 pub body_type: Option<String>,
16 pub response_type: String,
17 pub module_name: String,
18 pub spec_name: Option<String>,
19 pub api_import_path: String,
20 pub query_keys_import_path: String,
21 pub param_list: String, pub param_names: String, pub path_param_names: String, pub schema_imports: String, pub description: String,
26 pub success_map_type: String, pub error_map_type: String, pub generic_result_type: String, pub import_runtime_path: String, }
31
32impl HookContext {
33 pub fn calculate_api_import_path(
38 module_name: &str,
39 _spec_name: Option<&str>,
40 apis_dir: Option<&str>,
41 ) -> String {
42 let module_depth = module_name.matches('/').count() + 1; let hooks_depth = 1; let total_depth = module_depth + hooks_depth;
45
46 if let Some(apis) = apis_dir {
47 let hooks_path = format!("src/hooks/{}", module_name);
50
51 let common_prefix = HookContext::find_common_prefix(&hooks_path, apis);
52 let hooks_relative = hooks_path
53 .strip_prefix(&common_prefix)
54 .unwrap_or(&hooks_path)
55 .trim_start_matches('/');
56 let apis_relative = apis
57 .strip_prefix(&common_prefix)
58 .unwrap_or(apis)
59 .trim_start_matches('/');
60
61 let hooks_depth_from_common = if hooks_relative.is_empty() {
62 0
63 } else {
64 hooks_relative.matches('/').count() + 1
65 };
66
67 let sanitized_module = sanitize_module_name(module_name);
68 if apis_relative.is_empty() {
69 format!(
70 "{}{}",
71 "../".repeat(hooks_depth_from_common),
72 sanitized_module
73 )
74 } else {
75 format!(
76 "{}{}/{}",
77 "../".repeat(hooks_depth_from_common),
78 apis_relative,
79 sanitized_module
80 )
81 }
82 } else {
83 let sanitized_module = sanitize_module_name(module_name);
85 format!("{}apis/{}", "../".repeat(total_depth), sanitized_module)
86 }
87 }
88
89 pub fn find_common_prefix(path1: &str, path2: &str) -> String {
91 let parts1: Vec<&str> = path1.split('/').collect();
92 let parts2: Vec<&str> = path2.split('/').collect();
93
94 let mut common = Vec::new();
95 let min_len = parts1.len().min(parts2.len());
96
97 for i in 0..min_len {
98 if parts1[i] == parts2[i] {
99 common.push(parts1[i]);
100 } else {
101 break;
102 }
103 }
104
105 common.join("/")
106 }
107
108 pub fn calculate_query_keys_import_path(
113 module_name: &str,
114 _spec_name: Option<&str>,
115 hooks_dir: Option<&str>,
116 query_keys_dir: Option<&str>,
117 ) -> String {
118 let module_depth = module_name.matches('/').count() + 1; let hooks_depth = 1; let total_depth = module_depth + hooks_depth;
121
122 if let (Some(hooks), Some(query_keys)) = (hooks_dir, query_keys_dir) {
123 let hooks_path = format!("{}/{}", hooks, module_name);
126
127 let common_prefix = HookContext::find_common_prefix(&hooks_path, query_keys);
128 let hooks_relative = hooks_path
129 .strip_prefix(&common_prefix)
130 .unwrap_or(&hooks_path)
131 .trim_start_matches('/');
132 let query_keys_relative = query_keys
133 .strip_prefix(&common_prefix)
134 .unwrap_or(query_keys)
135 .trim_start_matches('/');
136
137 let hooks_depth_from_common = if hooks_relative.is_empty() {
138 0
139 } else {
140 hooks_relative.matches('/').count() + 1
141 };
142
143 let sanitized_module = sanitize_module_name(module_name);
144 if query_keys_relative.is_empty() {
145 format!(
146 "{}{}",
147 "../".repeat(hooks_depth_from_common),
148 sanitized_module
149 )
150 } else {
151 format!(
152 "{}{}/{}",
153 "../".repeat(hooks_depth_from_common),
154 query_keys_relative,
155 sanitized_module
156 )
157 }
158 } else {
159 let sanitized_module = sanitize_module_name(module_name);
161 format!(
162 "{}query-keys/{}",
163 "../".repeat(total_depth),
164 sanitized_module
165 )
166 }
167 }
168
169 pub fn calculate_runtime_import_path(module_name: &str, _spec_name: Option<&str>) -> String {
174 let module_depth = module_name.matches('/').count() + 1; let hooks_depth = 1; let total_depth = module_depth + hooks_depth;
179
180 format!("{}runtime", "../".repeat(total_depth))
181 }
182}