1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
5#[serde(rename_all = "lowercase")]
6pub enum Language {
7 TypeScript,
8 JavaScript,
9 Tsx,
10 Jsx,
11 Python,
12 Go,
13 Rust,
14 Java,
15 C,
16 Cpp,
17 CSharp,
18 Php,
19 Ruby,
20 Swift,
21 Kotlin,
22 Dart,
23 Svelte,
24 Vue,
25 Liquid,
26 Pascal,
27 Scala,
28 MoonBit,
29 Unknown,
30}
31
32impl Language {
33 pub fn as_str(self) -> &'static str {
34 match self {
35 Self::TypeScript => "typescript",
36 Self::JavaScript => "javascript",
37 Self::Tsx => "tsx",
38 Self::Jsx => "jsx",
39 Self::Python => "python",
40 Self::Go => "go",
41 Self::Rust => "rust",
42 Self::Java => "java",
43 Self::C => "c",
44 Self::Cpp => "cpp",
45 Self::CSharp => "csharp",
46 Self::Php => "php",
47 Self::Ruby => "ruby",
48 Self::Swift => "swift",
49 Self::Kotlin => "kotlin",
50 Self::Dart => "dart",
51 Self::Svelte => "svelte",
52 Self::Vue => "vue",
53 Self::Liquid => "liquid",
54 Self::Pascal => "pascal",
55 Self::Scala => "scala",
56 Self::MoonBit => "moonbit",
57 Self::Unknown => "unknown",
58 }
59 }
60
61 pub fn is_unknown(self) -> bool {
62 self == Self::Unknown
63 }
64}
65
66impl fmt::Display for Language {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 f.write_str(self.as_str())
69 }
70}
71
72impl std::str::FromStr for Language {
73 type Err = ();
74
75 fn from_str(s: &str) -> Result<Self, Self::Err> {
76 Ok(match s {
77 "typescript" => Self::TypeScript,
78 "javascript" => Self::JavaScript,
79 "tsx" => Self::Tsx,
80 "jsx" => Self::Jsx,
81 "python" => Self::Python,
82 "go" => Self::Go,
83 "rust" => Self::Rust,
84 "java" => Self::Java,
85 "c" => Self::C,
86 "cpp" => Self::Cpp,
87 "csharp" => Self::CSharp,
88 "php" => Self::Php,
89 "ruby" => Self::Ruby,
90 "swift" => Self::Swift,
91 "kotlin" => Self::Kotlin,
92 "dart" => Self::Dart,
93 "svelte" => Self::Svelte,
94 "vue" => Self::Vue,
95 "liquid" => Self::Liquid,
96 "pascal" => Self::Pascal,
97 "scala" => Self::Scala,
98 "moonbit" => Self::MoonBit,
99 _ => Self::Unknown,
100 })
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
105#[serde(rename_all = "snake_case")]
106pub enum NodeKind {
107 File,
108 Module,
109 Class,
110 Struct,
111 Interface,
112 Trait,
113 Protocol,
114 Function,
115 Method,
116 Property,
117 Field,
118 Variable,
119 Constant,
120 Enum,
121 EnumMember,
122 TypeAlias,
123 Namespace,
124 Parameter,
125 Import,
126 Export,
127 Route,
128 Component,
129}
130
131impl NodeKind {
132 pub fn as_str(self) -> &'static str {
133 match self {
134 Self::File => "file",
135 Self::Module => "module",
136 Self::Class => "class",
137 Self::Struct => "struct",
138 Self::Interface => "interface",
139 Self::Trait => "trait",
140 Self::Protocol => "protocol",
141 Self::Function => "function",
142 Self::Method => "method",
143 Self::Property => "property",
144 Self::Field => "field",
145 Self::Variable => "variable",
146 Self::Constant => "constant",
147 Self::Enum => "enum",
148 Self::EnumMember => "enum_member",
149 Self::TypeAlias => "type_alias",
150 Self::Namespace => "namespace",
151 Self::Parameter => "parameter",
152 Self::Import => "import",
153 Self::Export => "export",
154 Self::Route => "route",
155 Self::Component => "component",
156 }
157 }
158}
159
160impl fmt::Display for NodeKind {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 f.write_str(self.as_str())
163 }
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
167#[serde(rename_all = "snake_case")]
168pub enum EdgeKind {
169 Contains,
170 Calls,
171 Imports,
172 Exports,
173 Extends,
174 Implements,
175 References,
176 TypeOf,
177 Returns,
178 Instantiates,
179 Overrides,
180 Decorates,
181}
182
183impl EdgeKind {
184 pub fn as_str(self) -> &'static str {
185 match self {
186 Self::Contains => "contains",
187 Self::Calls => "calls",
188 Self::Imports => "imports",
189 Self::Exports => "exports",
190 Self::Extends => "extends",
191 Self::Implements => "implements",
192 Self::References => "references",
193 Self::TypeOf => "type_of",
194 Self::Returns => "returns",
195 Self::Instantiates => "instantiates",
196 Self::Overrides => "overrides",
197 Self::Decorates => "decorates",
198 }
199 }
200}
201
202impl fmt::Display for EdgeKind {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.write_str(self.as_str())
205 }
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct Node {
210 pub id: String,
211 pub kind: NodeKind,
212 pub name: String,
213 pub qualified_name: String,
214 pub file_path: String,
215 pub language: Language,
216 pub start_line: i64,
217 pub end_line: i64,
218 pub start_column: i64,
219 pub end_column: i64,
220 pub docstring: Option<String>,
221 pub signature: Option<String>,
222 pub visibility: Option<String>,
223 pub is_exported: bool,
224 pub is_async: bool,
225 pub is_static: bool,
226 pub is_abstract: bool,
227 pub updated_at: i64,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct Edge {
232 pub id: Option<i64>,
233 pub source: String,
234 pub target: String,
235 pub kind: EdgeKind,
236 pub line: Option<i64>,
237 pub col: Option<i64>,
238 pub provenance: Option<String>,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct UnresolvedReference {
243 pub from_node_id: String,
244 pub reference_name: String,
245 pub reference_kind: EdgeKind,
246 pub line: i64,
247 pub column: i64,
248 pub file_path: String,
249 pub language: Language,
250}
251
252#[derive(Debug, Clone)]
253pub struct ExtractionResult {
254 pub nodes: Vec<Node>,
255 pub edges: Vec<Edge>,
256 pub unresolved_references: Vec<UnresolvedReference>,
257}
258
259#[derive(Debug, Clone)]
260pub struct FileRecord {
261 pub path: String,
262 pub content_hash: String,
263 pub language: Language,
264 pub size: u64,
265 pub modified_at: i64,
266 pub indexed_at: i64,
267 pub node_count: i64,
268}
269
270#[derive(Debug, Clone, Default, Serialize)]
271pub struct IndexResult {
272 pub success: bool,
273 pub files_indexed: i64,
274 pub files_skipped: i64,
275 pub files_errored: i64,
276 pub nodes_created: i64,
277 pub edges_created: i64,
278 pub errors: Vec<String>,
279 pub duration_ms: i64,
280}
281
282#[derive(Debug, Clone, Default, Serialize)]
283pub struct GraphStats {
284 pub file_count: i64,
285 pub node_count: i64,
286 pub edge_count: i64,
287 pub db_size_bytes: i64,
288 pub files_by_language: Vec<(String, i64)>,
289 pub nodes_by_kind: Vec<(String, i64)>,
290}
291
292#[derive(Debug, Clone, Default)]
293pub struct SearchOptions {
294 pub limit: i64,
295 pub kind: Option<NodeKind>,
296 pub language: Option<Language>,
297}
298
299#[derive(Debug, Clone, Serialize)]
300pub struct SearchResult {
301 pub node: Node,
302 pub score: f64,
303}
304
305#[derive(Debug, Clone, Serialize)]
306pub struct NodeEdge {
307 pub node: Node,
308 pub edge: Edge,
309}