Skip to main content

oramacore_client/
cloud.rs

1//! Orama Cloud client functionality.
2
3use serde::Serialize;
4
5use crate::collection::{ClusterConfig, CollectionManager, CollectionManagerConfig};
6use crate::error::Result;
7use crate::types::*;
8
9/// Configuration for OramaCloud
10#[derive(Debug, Clone)]
11pub struct ProjectManagerConfig {
12    pub project_id: String,
13    pub api_key: String,
14    pub cluster: Option<ClusterConfig>,
15    pub auth_jwt_url: Option<String>,
16}
17
18/// Cloud search parameters (uses datasources instead of indexes)
19#[derive(Debug, Clone, Serialize, Default)]
20pub struct CloudSearchParams {
21    pub term: String,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub mode: Option<SearchMode>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub limit: Option<u32>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub offset: Option<u32>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub properties: Option<Vec<String>>,
30    #[serde(rename = "where", skip_serializing_if = "Option::is_none")]
31    pub where_clause: Option<AnyObject>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub facets: Option<AnyObject>,
34    pub datasources: Vec<String>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub exact: Option<bool>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub threshold: Option<f64>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub tolerance: Option<u32>,
41    #[serde(rename = "userID", skip_serializing_if = "Option::is_none")]
42    pub user_id: Option<String>,
43}
44
45/// Data source operations namespace
46#[derive(Debug, Clone)]
47pub struct DataSourceNamespace {
48    index: crate::collection::Index,
49}
50
51impl DataSourceNamespace {
52    pub(crate) fn new(index: crate::collection::Index) -> Self {
53        Self { index }
54    }
55
56    /// Reindex the data source
57    pub async fn reindex(&self) -> Result<()> {
58        self.index.reindex().await
59    }
60
61    /// Insert documents into the data source
62    pub async fn insert_documents<T>(&self, documents: Vec<T>) -> Result<()>
63    where
64        T: serde::Serialize,
65    {
66        self.index.insert_documents(documents).await
67    }
68
69    /// Delete documents from the data source
70    pub async fn delete_documents(&self, document_ids: Vec<String>) -> Result<()> {
71        self.index.delete_documents(document_ids).await
72    }
73
74    /// Upsert documents in the data source
75    pub async fn upsert_documents<T>(&self, documents: Vec<T>) -> Result<()>
76    where
77        T: serde::Serialize,
78    {
79        self.index.upsert_documents(documents).await
80    }
81}
82
83/// Main Orama Cloud client
84#[derive(Debug, Clone)]
85pub struct OramaCloud {
86    client: CollectionManager,
87}
88
89impl OramaCloud {
90    /// Create a new OramaCloud client
91    pub async fn new(config: ProjectManagerConfig) -> Result<Self> {
92        // Use CollectionManager internally with project_id as collection_id
93        let mut collection_config = CollectionManagerConfig::new(config.project_id, config.api_key);
94        if let Some(cluster) = config.cluster {
95            collection_config = collection_config.with_cluster(cluster);
96        }
97        if let Some(auth_jwt_url) = config.auth_jwt_url {
98            collection_config = collection_config.with_auth_jwt_url(auth_jwt_url);
99        }
100
101        let client = CollectionManager::new(collection_config).await?;
102
103        Ok(Self { client })
104    }
105
106    /// Perform a search with datasources parameter
107    pub async fn search<T>(&self, params: &CloudSearchParams) -> Result<SearchResult<T>>
108    where
109        T: for<'de> serde::Deserialize<'de>,
110    {
111        // Convert CloudSearchParams to SearchParams
112        let search_params = SearchParams {
113            term: params.term.clone(),
114            mode: params.mode.clone(),
115            limit: params.limit,
116            offset: params.offset,
117            properties: params.properties.clone(),
118            where_clause: params.where_clause.clone(),
119            facets: params.facets.clone(),
120            indexes: Some(params.datasources.clone()), // Map datasources to indexes
121            datasource_ids: None,
122            exact: params.exact,
123            threshold: params.threshold,
124            tolerance: params.tolerance,
125            user_id: params.user_id.clone(),
126        };
127
128        self.client.search(&search_params).await
129    }
130
131    /// Get a data source namespace for operations
132    pub fn data_source(&self, id: String) -> DataSourceNamespace {
133        let index = self.client.index.set(id);
134        DataSourceNamespace::new(index)
135    }
136
137    /// Access to AI operations
138    pub fn ai(&self) -> &crate::collection::AiNamespace {
139        &self.client.ai
140    }
141
142    /// Access to collections operations
143    pub fn collections(&self) -> &crate::collection::CollectionsNamespace {
144        &self.client.collections
145    }
146
147    /// Access to index operations
148    pub fn index(&self) -> &crate::collection::IndexNamespace {
149        &self.client.index
150    }
151
152    /// Access to hooks operations
153    pub fn hooks(&self) -> &crate::collection::HooksNamespace {
154        &self.client.hooks
155    }
156
157    /// Access to system prompts operations
158    pub fn system_prompts(&self) -> &crate::collection::SystemPromptsNamespace {
159        &self.client.system_prompts
160    }
161
162    /// Access to tools operations
163    pub fn tools(&self) -> &crate::collection::ToolsNamespace {
164        &self.client.tools
165    }
166}
167
168// Builder implementations
169impl ProjectManagerConfig {
170    /// Create a new ProjectManagerConfig
171    pub fn new<S: Into<String>>(project_id: S, api_key: S) -> Self {
172        Self {
173            project_id: project_id.into(),
174            api_key: api_key.into(),
175            cluster: None,
176            auth_jwt_url: None,
177        }
178    }
179
180    /// Set cluster configuration
181    pub fn with_cluster(mut self, cluster: ClusterConfig) -> Self {
182        self.cluster = Some(cluster);
183        self
184    }
185
186    /// Set auth JWT URL
187    pub fn with_auth_jwt_url<S: Into<String>>(mut self, url: S) -> Self {
188        self.auth_jwt_url = Some(url.into());
189        self
190    }
191}
192
193impl CloudSearchParams {
194    /// Create a new CloudSearchParams
195    pub fn new<S: Into<String>>(term: S, datasources: Vec<String>) -> Self {
196        Self {
197            term: term.into(),
198            datasources,
199            ..Default::default()
200        }
201    }
202
203    /// Set search mode
204    pub fn with_mode(mut self, mode: SearchMode) -> Self {
205        self.mode = Some(mode);
206        self
207    }
208
209    /// Set limit
210    pub fn with_limit(mut self, limit: u32) -> Self {
211        self.limit = Some(limit);
212        self
213    }
214
215    /// Set offset
216    pub fn with_offset(mut self, offset: u32) -> Self {
217        self.offset = Some(offset);
218        self
219    }
220
221    /// Set properties to search in
222    pub fn with_properties(mut self, properties: Vec<String>) -> Self {
223        self.properties = Some(properties);
224        self
225    }
226
227    /// Set where clause
228    pub fn with_where(mut self, where_clause: AnyObject) -> Self {
229        self.where_clause = Some(where_clause);
230        self
231    }
232
233    /// Set facets
234    pub fn with_facets(mut self, facets: AnyObject) -> Self {
235        self.facets = Some(facets);
236        self
237    }
238
239    /// Set exact matching
240    pub fn with_exact(mut self, exact: bool) -> Self {
241        self.exact = Some(exact);
242        self
243    }
244
245    /// Set similarity threshold
246    pub fn with_threshold(mut self, threshold: f64) -> Self {
247        self.threshold = Some(threshold);
248        self
249    }
250
251    /// Set tolerance
252    pub fn with_tolerance(mut self, tolerance: u32) -> Self {
253        self.tolerance = Some(tolerance);
254        self
255    }
256
257    /// Set user ID
258    pub fn with_user_id<S: Into<String>>(mut self, user_id: S) -> Self {
259        self.user_id = Some(user_id.into());
260        self
261    }
262}