open_kioku_storage/
lib.rs1use open_kioku_core::{
2 CodeChunk, File, FileId, GraphEdge, GraphNode, ImpactReport, Import, IndexManifest,
3 SearchResult, Symbol, SymbolId, SymbolOccurrence, TestTarget,
4};
5use open_kioku_errors::Result;
6use std::path::Path;
7
8pub trait MetadataStore: Send + Sync {
9 fn initialize(&self) -> Result<()>;
10 fn put_manifest(&self, manifest: &IndexManifest) -> Result<()>;
11 fn manifest(&self) -> Result<Option<IndexManifest>>;
12 fn replace_index(&self, data: IndexData<'_>) -> Result<()>;
13 fn list_files(&self, limit: usize, offset: usize) -> Result<Vec<File>>;
14 fn get_file_by_path(&self, path: &Path) -> Result<Option<File>>;
15 fn list_symbols(&self, query: Option<&str>, limit: usize, offset: usize)
16 -> Result<Vec<Symbol>>;
17 fn symbol_by_id(&self, id: &SymbolId) -> Result<Option<Symbol>>;
18 fn chunks_for_file(&self, file_id: &FileId) -> Result<Vec<CodeChunk>>;
19 fn all_chunks(&self) -> Result<Vec<CodeChunk>>;
20 fn tests(&self) -> Result<Vec<TestTarget>>;
21 fn imports(&self) -> Result<Vec<Import>>;
22 fn references_for_symbol(&self, id: &SymbolId, limit: usize) -> Result<Vec<SymbolOccurrence>>;
23 fn occurrences_for_file(&self, file_id: &FileId) -> Result<Vec<SymbolOccurrence>>;
24 fn symbols_for_file(&self, _file_id: &FileId) -> Result<Vec<Symbol>> {
25 Ok(Vec::new())
26 }
27 fn find_chunks_containing(&self, query: &str, limit: usize) -> Result<Vec<CodeChunk>> {
28 let chunks = self.all_chunks()?;
29 let mut results = Vec::new();
30 for chunk in chunks {
31 if chunk.text.contains(query) {
32 results.push(chunk);
33 if results.len() >= limit {
34 break;
35 }
36 }
37 }
38 Ok(results)
39 }
40 fn find_files_by_path_pattern(&self, pattern: &str) -> Result<Vec<File>> {
41 let files = self.list_files(usize::MAX, 0)?;
42 let lower_pattern = pattern.to_ascii_lowercase();
43 Ok(files
44 .into_iter()
45 .filter(|f| {
46 f.path
47 .to_string_lossy()
48 .to_ascii_lowercase()
49 .contains(&lower_pattern)
50 })
51 .collect())
52 }
53 fn tests_for_files(&self, file_ids: &[FileId]) -> Result<Vec<TestTarget>> {
54 let tests = self.tests()?;
55 let set = file_ids.iter().collect::<std::collections::HashSet<_>>();
56 Ok(tests
57 .into_iter()
58 .filter(|t| set.contains(&t.file_id))
59 .collect())
60 }
61}
62
63pub struct IndexData<'a> {
64 pub manifest: &'a IndexManifest,
65 pub files: &'a [File],
66 pub symbols: &'a [Symbol],
67 pub chunks: &'a [CodeChunk],
68 pub tests: &'a [TestTarget],
69 pub imports: &'a [Import],
70 pub occurrences: &'a [SymbolOccurrence],
71}
72
73pub trait GraphStore: Send + Sync {
74 fn replace_graph(&self, nodes: &[GraphNode], edges: &[GraphEdge]) -> Result<()>;
75 fn neighbors(&self, node: &str, limit: usize) -> Result<(Vec<GraphNode>, Vec<GraphEdge>)>;
76 fn shortest_path(&self, from: &str, to: &str, max_depth: usize) -> Result<Vec<GraphEdge>>;
77}
78
79pub trait SearchIndex: Send + Sync {
80 fn rebuild(&mut self, chunks: &[CodeChunk], files: &[File], symbols: &[Symbol]) -> Result<()>;
81 fn search(&self, query: &str, limit: usize) -> Result<Vec<SearchResult>>;
82}
83
84pub trait ImpactStore: Send + Sync {
85 fn impact_for_file(&self, path: &Path) -> Result<ImpactReport>;
86}
87
88pub trait OkStore: MetadataStore + GraphStore {}
90impl<T: MetadataStore + GraphStore> OkStore for T {}