pub mod crud;
pub mod database;
pub mod schema_models;
pub mod schema_traits;
pub use schema_models::*;
pub use schema_traits::*;
use anyhow::Result;
use sqlx::SqlitePool;
pub struct EntityManager {
pub pool: SqlitePool,
}
impl EntityManager {
pub fn new(pool: SqlitePool) -> Self {
Self { pool }
}
pub fn get_pool(&self) -> &SqlitePool {
&self.pool
}
pub async fn create_project(&self, name: String, description: String) -> Result<Project> {
crud::projects::create(&self.pool, name, description).await
}
pub async fn get_project(&self, id: &str) -> Result<Option<Project>> {
crud::projects::get_by_id(&self.pool, id).await
}
pub async fn list_active_projects(&self) -> Result<Vec<Project>> {
crud::projects::list_active(&self.pool).await
}
pub async fn create_feature(&self, name: String, description: String) -> Result<Feature> {
let project = self.get_current_project().await?;
let project_id = project.map(|p| p.id).unwrap_or_else(|| "P001".to_string());
crud::features::create(&self.pool, project_id, name, description, None).await
}
pub async fn create_feature_full(
&self,
project_id: String,
name: String,
description: String,
category: Option<String>,
) -> Result<Feature> {
crud::features::create(&self.pool, project_id, name, description, category).await
}
pub async fn get_feature(&self, id: &str) -> Result<Option<Feature>> {
crud::features::get_by_id(&self.pool, id).await
}
pub async fn list_features_by_project(&self, project_id: &str) -> Result<Vec<Feature>> {
crud::features::list_by_project(&self.pool, project_id).await
}
pub async fn list_features(&self) -> Result<Vec<Feature>> {
let project = self.get_current_project().await?;
if let Some(project) = project {
self.list_features_by_project(&project.id).await
} else {
Ok(vec![])
}
}
pub async fn update_feature_state(&self, id: &str, new_state: FeatureState) -> Result<()> {
crud::features::update_state(&self.pool, id, new_state).await
}
pub async fn create_task(&self, title: String, _description: String) -> Result<Task> {
let project = self.get_current_project().await?;
let project_id = project.map(|p| p.id).unwrap_or_else(|| "P001".to_string());
let features = self.list_features_by_project(&project_id).await?;
let feature_id = features
.first()
.map(|f| f.id.clone())
.unwrap_or_else(|| "F00001".to_string());
crud::tasks::create(
&self.pool,
project_id,
feature_id,
title,
"feature".to_string(),
)
.await
}
pub async fn create_task_full(
&self,
project_id: String,
feature_id: String,
task_description: String,
category: String,
) -> Result<Task> {
crud::tasks::create(
&self.pool,
project_id,
feature_id,
task_description,
category,
)
.await
}
pub async fn get_task(&self, id: &str) -> Result<Option<Task>> {
crud::tasks::get_by_id(&self.pool, id).await
}
pub async fn list_tasks_by_project(
&self,
project_id: &str,
status: Option<TaskStatus>,
) -> Result<Vec<Task>> {
crud::tasks::list_by_project(&self.pool, project_id, status).await
}
pub async fn list_tasks(&self) -> Result<Vec<Task>> {
let project = self.get_current_project().await?;
if let Some(project) = project {
self.list_tasks_by_project(&project.id, None).await
} else {
Ok(vec![])
}
}
pub async fn update_task_status(&self, id: &str, new_status: TaskStatus) -> Result<()> {
crud::tasks::update_status(&self.pool, id, new_status).await
}
pub async fn update_task(&self, task: Task) -> Result<()> {
crud::tasks::update(&self.pool, &task).await
}
pub async fn create_session(
&self,
project_id: String,
title: String,
focus: String,
) -> Result<Session> {
crud::sessions::create(&self.pool, project_id, title, Some(focus)).await
}
pub async fn get_session(&self, id: &str) -> Result<Option<Session>> {
crud::sessions::get_by_id(&self.pool, id).await
}
pub async fn list_sessions_by_project(&self, project_id: &str) -> Result<Vec<Session>> {
crud::sessions::list_by_project(&self.pool, project_id).await
}
pub async fn complete_session(&self, id: &str, summary: String) -> Result<()> {
crud::sessions::complete(&self.pool, id, summary).await
}
pub async fn create_directive(
&self,
project_id: String,
title: String,
rule: String,
category: DirectiveCategory,
priority: Priority,
) -> Result<Directive> {
crud::directives::create(&self.pool, project_id, title, rule, category, priority).await
}
pub async fn get_directive(&self, id: &str) -> Result<Option<Directive>> {
crud::directives::get_by_id(&self.pool, id).await
}
pub async fn list_active_directives(&self, project_id: &str) -> Result<Vec<Directive>> {
crud::directives::list_active_by_project(&self.pool, project_id).await
}
pub async fn deactivate_directive(&self, id: &str) -> Result<()> {
crud::directives::deactivate(&self.pool, id).await
}
pub async fn delete_project(&self, id: &str) -> Result<()> {
crud::projects::delete(&self.pool, id).await
}
pub async fn delete_feature(&self, id: &str) -> Result<()> {
crud::features::delete(&self.pool, id).await
}
pub async fn delete_task(&self, id: &str) -> Result<()> {
crud::tasks::delete(&self.pool, id).await
}
pub async fn delete_session(&self, id: &str) -> Result<()> {
crud::sessions::delete(&self.pool, id).await
}
pub async fn get_current_project(&self) -> Result<Option<Project>> {
let projects = self.list_active_projects().await?;
Ok(projects.into_iter().next())
}
pub async fn create_note_link(
&self,
_note_id: String,
_entity_id: String,
_entity_type: String,
_relationship_type: String,
) -> Result<String> {
Ok("link_placeholder".to_string())
}
pub async fn remove_note_link(&self, _link_id: &str) -> Result<bool> {
Ok(true)
}
pub async fn get_bidirectional_links(
&self,
_id: &str,
_entity_type: Option<String>,
) -> Result<Vec<String>> {
Ok(vec![])
}
pub async fn delete_directive(&self, id: &str) -> Result<()> {
crud::directives::delete(&self.pool, id).await
}
}