Skip to main content

aimcal_core/
store.rs

1// SPDX-FileCopyrightText: 2025-2026 Zexin Yuan <aim@yzx9.xyz>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5pub mod caldav;
6pub mod local;
7
8pub use caldav::CaldavStore;
9pub use local::LocalStore;
10
11use std::error::Error;
12
13use aimcal_ical::{VEvent, VTodo};
14use async_trait::async_trait;
15
16use crate::{EventPatch, TodoPatch};
17
18/// Error type for store operations that is Send + Sync.
19pub type StoreError = Box<dyn Error + Send + Sync>;
20
21/// Result of a backend synchronization operation.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct SyncResult {
24    /// Number of items created during synchronization.
25    pub created: usize,
26    /// Number of items updated during synchronization.
27    pub updated: usize,
28    /// Number of items deleted during synchronization.
29    pub deleted: usize,
30}
31
32/// Store trait for storing and synchronizing events and todos.
33///
34/// This trait abstracts different storage backends (local ICS files, `CalDAV` servers, etc.)
35/// providing a unified interface for CRUD operations on calendar items.
36#[async_trait]
37pub trait Store: Send + Sync {
38    /// Creates a new event in the store.
39    ///
40    /// # Arguments
41    ///
42    /// * `uid` - The unique identifier for the event
43    /// * `event` - The event to create
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if the event cannot be created in the store.
48    async fn create_event(&self, uid: &str, event: &VEvent<String>) -> Result<String, StoreError>;
49
50    /// Retrieves an event from the store by UID.
51    ///
52    /// # Arguments
53    ///
54    /// * `uid` - The unique identifier of the event to retrieve
55    ///
56    /// # Errors
57    ///
58    /// Returns an error if the event is not found or cannot be retrieved.
59    async fn get_event(&self, uid: &str) -> Result<VEvent<String>, StoreError>;
60
61    /// Updates an existing event in the store.
62    ///
63    /// # Arguments
64    ///
65    /// * `uid` - The unique identifier of the event to update
66    /// * `patch` - The patch to apply to the event
67    ///
68    /// # Errors
69    ///
70    /// Returns an error if the event is not found or cannot be updated.
71    async fn update_event(
72        &self,
73        uid: &str,
74        patch: &EventPatch,
75    ) -> Result<VEvent<String>, StoreError>;
76
77    /// Deletes an event from the store.
78    ///
79    /// # Arguments
80    ///
81    /// * `uid` - The unique identifier of the event to delete
82    ///
83    /// # Errors
84    ///
85    /// Returns an error if the event is not found or cannot be deleted.
86    async fn delete_event(&self, uid: &str) -> Result<(), StoreError>;
87
88    /// Creates a new todo in the store.
89    ///
90    /// # Arguments
91    ///
92    /// * `uid` - The unique identifier for the todo
93    /// * `todo` - The todo to create
94    ///
95    /// # Errors
96    ///
97    /// Returns an error if the todo cannot be created in the store.
98    async fn create_todo(&self, uid: &str, todo: &VTodo<String>) -> Result<String, StoreError>;
99
100    /// Retrieves a todo from the store by UID.
101    ///
102    /// # Arguments
103    ///
104    /// * `uid` - The unique identifier of the todo to retrieve
105    ///
106    /// # Errors
107    ///
108    /// Returns an error if the todo is not found or cannot be retrieved.
109    async fn get_todo(&self, uid: &str) -> Result<VTodo<String>, StoreError>;
110
111    /// Updates an existing todo in the store.
112    ///
113    /// # Arguments
114    ///
115    /// * `uid` - The unique identifier of the todo to update
116    /// * `patch` - The patch to apply to the todo
117    ///
118    /// # Errors
119    ///
120    /// Returns an error if the todo is not found or cannot be updated.
121    async fn update_todo(&self, uid: &str, patch: &TodoPatch) -> Result<VTodo<String>, StoreError>;
122
123    /// Deletes a todo from the store.
124    ///
125    /// # Arguments
126    ///
127    /// * `uid` - The unique identifier of the todo to delete
128    ///
129    /// # Errors
130    ///
131    /// Returns an error if the todo is not found or cannot be deleted.
132    async fn delete_todo(&self, uid: &str) -> Result<(), StoreError>;
133
134    /// Lists all events in the store.
135    ///
136    /// # Errors
137    ///
138    /// Returns an error if the events cannot be listed.
139    async fn list_events(&self) -> Result<Vec<(String, VEvent<String>)>, StoreError>;
140
141    /// Lists all todos in the store.
142    ///
143    /// # Errors
144    ///
145    /// Returns an error if the todos cannot be listed.
146    async fn list_todos(&self) -> Result<Vec<(String, VTodo<String>)>, StoreError>;
147
148    /// Checks if a UID exists in the store.
149    ///
150    /// # Arguments
151    ///
152    /// * `uid` - The unique identifier to check
153    ///
154    /// # Returns
155    ///
156    /// `true` if the UID exists, `false` otherwise.
157    ///
158    /// # Errors
159    ///
160    /// Returns an error if the check cannot be performed.
161    async fn uid_exists(&self, uid: &str) -> Result<bool, StoreError>;
162
163    /// Returns the calendar identifier for this store.
164    ///
165    /// This identifies which calendar in the database items from this store belong to.
166    fn calendar_id(&self) -> &str;
167
168    /// Synchronizes the store with the local cache (database).
169    ///
170    /// This operation scans the store for changes and updates the local
171    /// database accordingly.
172    ///
173    /// # Returns
174    ///
175    /// A `SyncResult` containing counts of created, updated, and deleted items.
176    ///
177    /// # Errors
178    ///
179    /// Returns an error if synchronization fails.
180    async fn sync_cache(&self) -> Result<SyncResult, StoreError>;
181}