Skip to main content

codegraph/
types.rs

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, Copy, PartialEq, Eq)]
271pub enum FileListFormat {
272    Grouped,
273    Flat,
274    Tree,
275}
276
277impl std::str::FromStr for FileListFormat {
278    type Err = ();
279
280    fn from_str(s: &str) -> Result<Self, Self::Err> {
281        Ok(match s {
282            "grouped" => Self::Grouped,
283            "flat" => Self::Flat,
284            "tree" => Self::Tree,
285            _ => return Err(()),
286        })
287    }
288}
289
290#[derive(Debug, Clone)]
291pub struct FileListOptions {
292    pub format: FileListFormat,
293    pub path_filter: Option<String>,
294    pub pattern: Option<String>,
295    pub include_metadata: bool,
296    pub max_depth: Option<usize>,
297}
298
299#[derive(Debug, Clone, Serialize)]
300#[serde(rename_all = "camelCase")]
301pub struct FileListReport {
302    pub format: String,
303    pub path_filter: Option<String>,
304    pub pattern: Option<String>,
305    pub include_metadata: bool,
306    pub max_depth: Option<usize>,
307    pub total_files: usize,
308    pub files: Vec<FileListEntry>,
309    pub groups: Vec<FileLanguageGroup>,
310    pub tree: Vec<FileTreeEntry>,
311}
312
313#[derive(Debug, Clone, Serialize)]
314#[serde(rename_all = "camelCase")]
315pub struct FileListEntry {
316    pub path: String,
317    pub language: Language,
318    pub node_count: i64,
319    pub size: Option<u64>,
320    pub modified_at: Option<i64>,
321    pub indexed_at: Option<i64>,
322}
323
324#[derive(Debug, Clone, Serialize)]
325pub struct FileLanguageGroup {
326    pub language: Language,
327    pub count: usize,
328    pub files: Vec<FileListEntry>,
329}
330
331#[derive(Debug, Clone, Serialize)]
332#[serde(rename_all = "camelCase")]
333pub struct FileTreeEntry {
334    pub name: String,
335    pub path: String,
336    pub kind: String,
337    pub language: Option<Language>,
338    pub node_count: Option<i64>,
339    pub size: Option<u64>,
340    pub children: Vec<FileTreeEntry>,
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
344#[serde(rename_all = "snake_case")]
345pub enum IndexErrorCategory {
346    Read,
347    Parse,
348    Unsupported,
349    Lock,
350}
351
352impl IndexErrorCategory {
353    pub fn as_str(self) -> &'static str {
354        match self {
355            Self::Read => "read",
356            Self::Parse => "parse",
357            Self::Unsupported => "unsupported",
358            Self::Lock => "lock",
359        }
360    }
361}
362
363impl fmt::Display for IndexErrorCategory {
364    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
365        f.write_str(self.as_str())
366    }
367}
368
369#[derive(Debug, Clone, Serialize)]
370pub struct IndexError {
371    pub category: IndexErrorCategory,
372    pub path: String,
373    pub message: String,
374}
375
376#[derive(Debug, Clone, Default, Serialize)]
377pub struct IndexResult {
378    pub success: bool,
379    pub files_indexed: i64,
380    pub files_skipped: i64,
381    pub files_deleted: i64,
382    pub files_errored: i64,
383    pub nodes_created: i64,
384    pub edges_created: i64,
385    pub errors: Vec<IndexError>,
386    pub duration_ms: i64,
387}
388
389#[derive(Debug, Clone, Default, Serialize)]
390pub struct GraphStats {
391    pub file_count: i64,
392    pub node_count: i64,
393    pub edge_count: i64,
394    pub db_size_bytes: i64,
395    pub oldest_indexed_at: Option<i64>,
396    pub last_indexed_at: Option<i64>,
397    pub newest_modified_at: Option<i64>,
398    pub stale_file_count: i64,
399    pub files_by_language: Vec<(String, i64)>,
400    pub nodes_by_kind: Vec<(String, i64)>,
401}
402
403#[derive(Debug, Clone, Default)]
404pub struct SearchOptions {
405    pub limit: i64,
406    pub kind: Option<NodeKind>,
407    pub language: Option<Language>,
408}
409
410#[derive(Debug, Clone, Serialize)]
411pub struct SearchResult {
412    pub node: Node,
413    pub score: f64,
414}
415
416#[derive(Debug, Clone, Serialize)]
417pub struct ContextReport {
418    pub query: String,
419    pub search_terms: Vec<String>,
420    pub matches: Vec<ContextMatch>,
421    pub files: Vec<ContextFileSummary>,
422    pub symbols: Vec<ContextSymbolSummary>,
423    pub warnings: Vec<String>,
424}
425
426#[derive(Debug, Clone, Serialize)]
427pub struct ContextMatch {
428    pub search_term: String,
429    pub reason: String,
430    pub score: f64,
431    pub node: Node,
432    pub code: Option<String>,
433}
434
435#[derive(Debug, Clone, Serialize)]
436pub struct ContextFileSummary {
437    pub path: String,
438    pub language: Language,
439    pub match_count: i64,
440    pub symbols: Vec<String>,
441}
442
443#[derive(Debug, Clone, Serialize)]
444pub struct ContextSymbolSummary {
445    pub name: String,
446    pub kind: NodeKind,
447    pub file_path: String,
448    pub start_line: i64,
449}
450
451#[derive(Debug, Clone, Serialize)]
452#[serde(rename_all = "camelCase")]
453pub struct ExploreReport {
454    pub query: String,
455    pub max_files: usize,
456    pub budget_guidance: String,
457    pub source_files: Vec<ExploreSourceFile>,
458    pub relationships: Vec<ExploreRelationship>,
459    pub additional_files: Vec<String>,
460    pub warnings: Vec<String>,
461    pub truncated: bool,
462    pub truncated_reason: Option<String>,
463}
464
465#[derive(Debug, Clone, Serialize)]
466#[serde(rename_all = "camelCase")]
467pub struct ExploreSourceFile {
468    pub path: String,
469    pub language: Language,
470    pub sections: Vec<ExploreSourceSection>,
471}
472
473#[derive(Debug, Clone, Serialize)]
474#[serde(rename_all = "camelCase")]
475pub struct ExploreSourceSection {
476    pub symbol: String,
477    pub kind: NodeKind,
478    pub start_line: i64,
479    pub end_line: i64,
480    pub reason: String,
481    pub code: String,
482    pub truncated: bool,
483}
484
485#[derive(Debug, Clone, Serialize)]
486#[serde(rename_all = "camelCase")]
487pub struct ExploreRelationship {
488    pub source: String,
489    pub target: String,
490    pub kind: EdgeKind,
491    pub file_path: String,
492    pub direction: String,
493}
494
495#[derive(Debug, Clone, Serialize)]
496#[serde(rename_all = "camelCase")]
497pub struct AffectedReport {
498    pub changed_files: Vec<String>,
499    pub affected_tests: Vec<String>,
500    pub debug: Vec<AffectedDebugEntry>,
501    pub warnings: Vec<String>,
502}
503
504#[derive(Debug, Clone, Serialize)]
505#[serde(rename_all = "camelCase")]
506pub struct AffectedDebugEntry {
507    pub changed_file: String,
508    pub reason: String,
509    pub matched_tests: Vec<String>,
510    pub matched_by: AffectedMatchSources,
511}
512
513#[derive(Debug, Clone, Serialize)]
514#[serde(rename_all = "camelCase")]
515pub struct AffectedMatchSources {
516    pub direct_test_input: Vec<String>,
517    pub import_dependents: Vec<String>,
518    pub moonbit_same_package: Vec<String>,
519    pub moonbit_package_dependents: Vec<String>,
520    pub rust_name_heuristic: Vec<String>,
521    pub rust_workspace_heuristic: Vec<String>,
522}
523
524#[derive(Debug, Clone, Serialize)]
525pub struct NodeEdge {
526    pub node: Node,
527    pub edge: Edge,
528    pub depth: usize,
529}
530
531#[derive(Debug, Clone, Serialize)]
532pub struct GraphPath {
533    pub nodes: Vec<Node>,
534    pub edges: Vec<Edge>,
535}