Skip to main content

time_tracker_plugin_sdk/
api.rs

1//! Plugin API interface trait
2//!
3//! This trait abstracts the Plugin API so that plugins can work with
4//! any implementation. The concrete implementation in the core app
5//! provides access to Database and ExtensionRegistry.
6
7use crate::extensions::{EntityType, SchemaChange, ModelField, QueryFilter};
8use serde_json;
9use serde::{Deserialize, Serialize};
10
11/// Filters for querying activities
12/// 
13/// Used with `get_activities()` to filter results at the database level.
14/// All fields are optional - if not provided, no filtering is applied for that field.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ActivityFilters {
17    /// Exclude idle activities (where is_idle = true)
18    pub exclude_idle: Option<bool>,
19    /// Filter by category IDs (activities must have category_id in this list)
20    pub category_ids: Option<Vec<i64>>,
21}
22
23/// Abstract interface for plugins to interact with Core
24pub trait PluginAPIInterface: Send + Sync {
25    /// Register a database schema extension
26    fn register_schema_extension(
27        &self,
28        entity_type: EntityType,
29        schema_changes: Vec<SchemaChange>,
30    ) -> Result<(), String>;
31    
32    /// Register a model extension
33    fn register_model_extension(
34        &self,
35        entity_type: EntityType,
36        model_fields: Vec<ModelField>,
37    ) -> Result<(), String>;
38    
39    /// Register query filters
40    fn register_query_filters(
41        &self,
42        entity_type: EntityType,
43        query_filters: Vec<QueryFilter>,
44    ) -> Result<(), String>;
45    
46    // ============================================================================
47    // Core Application Methods
48    // ============================================================================
49    
50    /// Get all categories (returns array of objects with core + extended fields)
51    fn get_categories(&self) -> Result<serde_json::Value, String>;
52    
53    /// Create a category; params may include plugin-extended field names and values
54    fn create_category(&self, params: serde_json::Value) -> Result<serde_json::Value, String>;
55    
56    /// Update a category; params may include plugin-extended fields
57    fn update_category(&self, params: serde_json::Value) -> Result<serde_json::Value, String>;
58    
59    /// Delete a category by ID
60    fn delete_category(&self, id: i64) -> Result<(), String>;
61    
62    /// Get activities in a time range with optional filters
63    /// 
64    /// # Parameters
65    /// - `start`: Start timestamp (Unix timestamp in seconds)
66    /// - `end`: End timestamp (Unix timestamp in seconds)
67    /// - `limit`: Optional maximum number of results
68    /// - `offset`: Optional offset for pagination
69    /// - `filters`: Optional filters to apply (exclude_idle, category_ids)
70    /// 
71    /// # Returns
72    /// Array of activity objects (id, started_at, duration_sec, is_idle, category_id, and any plugin-extended fields)
73    fn get_activities(
74        &self,
75        start: i64,
76        end: i64,
77        limit: Option<i64>,
78        offset: Option<i64>,
79        filters: Option<ActivityFilters>,
80    ) -> Result<serde_json::Value, String>;
81    
82    /// Get manual entries in a time range
83    fn get_manual_entries(&self, start: i64, end: i64) -> Result<serde_json::Value, String>;
84    
85    /// Create a manual entry
86    fn create_manual_entry(&self, params: serde_json::Value) -> Result<serde_json::Value, String>;
87    
88    /// Update a manual entry
89    fn update_manual_entry(&self, params: serde_json::Value) -> Result<serde_json::Value, String>;
90    
91    /// Delete a manual entry by ID
92    fn delete_manual_entry(&self, id: i64) -> Result<(), String>;
93    
94    // ============================================================================
95    // Plugin's Own Table Methods
96    // ============================================================================
97    
98    /// Insert a row into a table owned by this plugin
99    /// Returns: `{ "id": row_id }`
100    fn insert_own_table(&self, table: &str, data: serde_json::Value) -> Result<serde_json::Value, String>;
101    
102    /// Query rows from a table owned by this plugin
103    /// Returns: array of row objects
104    fn query_own_table(
105        &self,
106        table: &str,
107        filters: Option<serde_json::Value>,
108        order_by: Option<&str>,
109        limit: Option<i64>,
110    ) -> Result<serde_json::Value, String>;
111    
112    /// Update a row in a table owned by this plugin
113    /// Returns: `{ "updated": count }`
114    fn update_own_table(&self, table: &str, id: i64, data: serde_json::Value) -> Result<serde_json::Value, String>;
115    
116    /// Delete a row from a table owned by this plugin
117    /// Returns: `{ "deleted": count }`
118    fn delete_own_table(&self, table: &str, id: i64) -> Result<serde_json::Value, String>;
119    
120    /// Run aggregations on a table owned by this plugin
121    /// Returns: object with keys such as `total_count`, `sum_<col>`, `avg_<col>`, `groups` (when `group_by` is used)
122    fn aggregate_own_table(
123        &self,
124        table: &str,
125        filters: Option<serde_json::Value>,
126        aggregations: serde_json::Value,
127    ) -> Result<serde_json::Value, String>;
128    
129    // ============================================================================
130    // Cross-Plugin Methods
131    // ============================================================================
132    
133    /// Query a table owned by another plugin
134    /// 
135    /// # Parameters
136    /// - `plugin_id`: ID of the plugin that owns the table
137    /// - `table`: Table name to query
138    /// - `filters`: Optional filter conditions (same format as select_table - JSON object with column names to values)
139    /// - `order_by`: Optional ordering (e.g., "created_at DESC")
140    /// - `limit`: Optional row limit (max 10000)
141    /// 
142    /// # Returns
143    /// Array of row objects (same format as select_table)
144    /// 
145    /// # Errors
146    /// - Plugin not found
147    /// - Table not owned by specified plugin
148    /// - Table not exposed for cross-plugin queries
149    /// - Permission denied (not in allowed_plugins list)
150    fn query_plugin_table(
151        &self,
152        plugin_id: &str,
153        table: &str,
154        filters: Option<serde_json::Value>,
155        order_by: Option<&str>,
156        limit: Option<i64>,
157    ) -> Result<serde_json::Value, String>;
158    
159    // ============================================================================
160    // Deprecated Methods
161    // ============================================================================
162    
163    /// Call a database method by name with JSON parameters
164    /// 
165    /// # Deprecated
166    /// This method is deprecated. Use specific methods instead:
167    /// - `get_categories()`, `create_category()`, `update_category()`, `delete_category()` for categories
168    /// - `get_activities()` for activities
169    /// - `get_manual_entries()`, `create_manual_entry()`, `update_manual_entry()`, `delete_manual_entry()` for manual entries
170    /// - `query_own_table()`, `insert_own_table()`, `update_own_table()`, `delete_own_table()`, `aggregate_own_table()` for plugin tables
171    /// 
172    /// This method will be removed in a future major version.
173    #[deprecated(note = "Use specific methods instead: get_categories(), create_category(), query_own_table(), etc.")]
174    fn call_db_method(&self, method: &str, params: serde_json::Value) -> Result<serde_json::Value, String>;
175}