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}