oh-my-todo 0.2.0

Local-first terminal task manager with a mouse-first TUI and CLI.
Documentation
use crate::application::error::AppError;
use crate::application::{AppStateService, MaintenanceService, SpaceService, TaskService};
use crate::storage::{AppRepository, DataPaths, FilesystemRepository, RepositorySnapshot};
use std::path::{Path, PathBuf};
use std::sync::Arc;

#[derive(Debug, Clone, Default)]
pub struct BootstrapOptions {
    pub data_root: Option<PathBuf>,
}

#[derive(Clone)]
pub struct AppContext {
    repository: Arc<dyn AppRepository>,
    pub startup: RepositorySnapshot,
    pub app_state_service: AppStateService,
    pub maintenance_service: MaintenanceService,
    pub space_service: SpaceService,
    pub task_service: TaskService,
}

impl AppContext {
    pub fn data_root(&self) -> &Path {
        self.repository.paths().root()
    }
}

pub fn bootstrap(options: BootstrapOptions) -> Result<AppContext, AppError> {
    let paths = match options.data_root {
        Some(root) => DataPaths::from_root(root),
        None => DataPaths::resolve_default()?,
    };

    let repository: Arc<dyn AppRepository> = Arc::new(FilesystemRepository::new(paths));
    repository.initialize()?;
    let maintenance_service = MaintenanceService::new(repository.clone());
    maintenance_service.recover_pending_operation()?;
    let startup = repository.initialize()?;
    let app_state_service = AppStateService::new(repository.clone());
    let maintenance_service = MaintenanceService::new(repository.clone());
    let space_service = SpaceService::new(repository.clone());
    let task_service = TaskService::new(repository.clone());

    Ok(AppContext {
        repository,
        startup,
        app_state_service,
        maintenance_service,
        space_service,
        task_service,
    })
}