repoask_wasm/lib.rs
1//! repoask WASM bindings for browser usage.
2//!
3//! Provides the same search functionality as the CLI, but operates on
4//! in-memory file contents instead of filesystem paths.
5
6use wasm_bindgen::prelude::*;
7
8use repoask_core::index::InvertedIndex;
9use repoask_core::types::IndexDocument;
10
11/// A search index that can be built from file contents and queried.
12///
13/// Usage from JavaScript:
14/// ```js
15/// const index = new RepoIndex();
16/// index.addFile("src/auth.ts", sourceCode);
17/// index.addFile("README.md", readmeContent);
18/// index.build();
19/// const results = index.search("authentication", 10);
20/// ```
21#[wasm_bindgen]
22pub struct RepoIndex {
23 documents: Vec<IndexDocument>,
24 index: Option<InvertedIndex>,
25}
26
27#[wasm_bindgen]
28impl RepoIndex {
29 /// Create a new empty index.
30 #[wasm_bindgen(constructor)]
31 pub fn new() -> Self {
32 Self {
33 documents: Vec::new(),
34 index: None,
35 }
36 }
37
38 /// Add a file to be indexed.
39 ///
40 /// Call this for each file before calling `build()`.
41 /// The filepath determines the parser used (e.g. `.ts` → oxc, `.md` → markdown).
42 #[wasm_bindgen(js_name = "addFile")]
43 pub fn add_file(&mut self, filepath: &str, content: &str) {
44 let docs = repoask_parser::parse_file_lenient(filepath, content);
45 self.documents.extend(docs);
46 }
47
48 /// Build the search index from all added files.
49 ///
50 /// Must be called after all `addFile()` calls and before `search()`.
51 pub fn build(&mut self) {
52 let docs = std::mem::take(&mut self.documents);
53 self.index = Some(InvertedIndex::build(docs));
54 }
55
56 /// Search the index and return results as a JSON string.
57 ///
58 /// Returns a JSON array of search results.
59 /// Each result is `{"Code": {...}}`, `{"Doc": {...}}`, or `{"Example": {...}}`.
60 pub fn search(&self, query: &str, limit: usize) -> Result<String, JsError> {
61 let index = self
62 .index
63 .as_ref()
64 .ok_or_else(|| JsError::new("index not built: call build() first"))?;
65
66 let results = index.search(query, limit);
67 serde_json::to_string(&results).map_err(|e| JsError::new(&e.to_string()))
68 }
69
70 /// Return the number of documents in the index.
71 #[wasm_bindgen(js_name = "docCount")]
72 pub fn doc_count(&self) -> usize {
73 match &self.index {
74 Some(idx) => idx.doc_count(),
75 None => self.documents.len(),
76 }
77 }
78}
79
80impl Default for RepoIndex {
81 fn default() -> Self {
82 Self::new()
83 }
84}