aven-core 0.1.12

Core library for the Aven local-first task manager
use anyhow::Result;
use sqlx::{Sqlite, SqliteConnection, pool::PoolConnection};

use crate::db::Database;
use crate::ids::{BASE32, TaskId, WorkspaceId};
use crate::operations::{
    DependencyOutcome, EpicLinkOutcome, LabelOutcome, TaskDraft, TaskOutcome, TaskUpdate,
    TaskUpdateOutcome,
};
use crate::types::Project;
use crate::workspaces::Workspace;

pub fn task_id(value: &str) -> TaskId {
    let mut encoded = value
        .bytes()
        .map(|byte| match byte.to_ascii_uppercase() {
            b'O' => '0',
            b'I' | b'L' => '1',
            byte if BASE32.contains(&byte) => char::from(byte),
            byte => char::from(BASE32[usize::from(byte) % BASE32.len()]),
        })
        .take(16)
        .collect::<String>();
    encoded.extend(std::iter::repeat_n('0', 16 - encoded.len()));
    encoded.parse().unwrap()
}

pub async fn acquire(database: &Database) -> Result<PoolConnection<Sqlite>> {
    database.acquire().await
}

pub async fn ensure_default_workspace(conn: &mut SqliteConnection) -> Result<Workspace> {
    crate::workspaces::ensure_default_workspace(conn).await
}

pub async fn create_workspace(conn: &mut SqliteConnection, name: &str) -> Result<Workspace> {
    crate::workspaces::create_workspace(conn, name).await
}

pub async fn create_project_in_workspace(
    conn: &mut SqliteConnection,
    workspace_id: &WorkspaceId,
    name: &str,
) -> Result<crate::projects::ProjectCreateOutcome> {
    crate::projects::create_project_in_workspace(conn, workspace_id, name).await
}

pub async fn resolve_or_create_project_in_workspace(
    conn: &mut SqliteConnection,
    workspace_id: &WorkspaceId,
    name: &str,
) -> Result<Project> {
    crate::projects::resolve_or_create_project_in_workspace(conn, workspace_id, name).await
}

pub async fn create_task(
    conn: &mut SqliteConnection,
    workspace: &Workspace,
    draft: TaskDraft,
) -> Result<TaskOutcome> {
    crate::operations::create_task(conn, workspace, draft).await
}

pub async fn update_task(
    conn: &mut SqliteConnection,
    workspace: &Workspace,
    task_id: &TaskId,
    update: TaskUpdate,
) -> Result<TaskUpdateOutcome> {
    crate::operations::update_task(conn, workspace, task_id, update).await
}

pub async fn set_task_deleted(
    conn: &mut SqliteConnection,
    workspace: &Workspace,
    task_id: &TaskId,
    deleted: bool,
) -> Result<TaskOutcome> {
    crate::operations::set_task_deleted(conn, workspace, task_id, deleted).await
}

pub async fn update_task_labels_in_workspace(
    conn: &mut SqliteConnection,
    workspace_id: &WorkspaceId,
    task_id: &TaskId,
    add: &[String],
    remove: &[String],
) -> Result<bool> {
    crate::operations::update_task_labels_in_workspace(conn, workspace_id, task_id, add, remove)
        .await
}

pub async fn add_task_dependency(
    conn: &mut SqliteConnection,
    workspace: &Workspace,
    task_id: &TaskId,
    depends_on_id: &TaskId,
) -> Result<DependencyOutcome> {
    crate::operations::add_task_dependency(conn, workspace, task_id, depends_on_id).await
}

pub async fn add_task_to_epic(
    conn: &mut SqliteConnection,
    workspace: &Workspace,
    child_id: &TaskId,
    epic_id: &TaskId,
) -> Result<EpicLinkOutcome> {
    crate::operations::add_task_to_epic(conn, workspace, child_id, epic_id).await
}

pub async fn create_label_operation(
    conn: &mut SqliteConnection,
    workspace: &Workspace,
    name: &str,
) -> Result<LabelOutcome> {
    crate::operations::create_label_operation(conn, workspace, name).await
}

pub async fn list_labels_in_workspace(
    conn: &mut SqliteConnection,
    workspace_id: &WorkspaceId,
    search: Option<&str>,
) -> Result<Vec<String>> {
    crate::labels::list_labels_in_workspace(conn, workspace_id, search).await
}

pub async fn get_meta(conn: &mut SqliteConnection, key: &str) -> Result<Option<String>> {
    crate::db::get_meta(conn, key).await
}

pub async fn set_meta(conn: &mut SqliteConnection, key: &str, value: &str) -> Result<()> {
    crate::db::set_meta(conn, key, value).await
}

#[cfg(test)]
pub async fn test_conn() -> (tempfile::TempDir, PoolConnection<Sqlite>) {
    let temp = tempfile::tempdir().unwrap();
    let database = Database::open(&temp.path().join("test.sqlite"))
        .await
        .unwrap();
    let conn = database.acquire().await.unwrap();
    (temp, conn)
}