libikarus 0.1.14

The core functionality of Ikarus wrapped neatly in a rust library
Documentation
use crate::args::validate::{
    validate_string_not_blank, ObjectValidationError, StringValidationError,
};
use crate::define_object;
use crate::objects::blueprint_folder::BlueprintFolder;
use crate::objects::id::TypedId;
use crate::objects::object::*;
use crate::objects::{ExpiredConnectionError, FromObjectScopeError};
use crate::persistence::project::ProjectError;
use crate::types::location::FolderPosition;
use sqrite::connection::{Connection, DbError, RcRefCellExtension};
use std::fmt::Debug;
use std::rc::Rc;
use tracing::*;

#[derive(thiserror::Error, Debug)]
pub enum BlueprintError {
    #[error("error interfacing with project: {0}")]
    ProjectError(#[from] ProjectError),
    #[error("connection has expired")]
    ExpiredConnection(#[from] ExpiredConnectionError),
    #[error("error interfacing with database: {0}")]
    DbError(#[from] DbError),
    #[error("unable to validate object: {0}")]
    ObjectValidationError(#[from] ObjectValidationError),
    #[error("unable to validate string argument: {0}")]
    StringValidationError(#[from] StringValidationError),
    #[error("unable to interface with blueprint as object: {0}")]
    ObjectError(#[from] ObjectHelperError),
    #[error("invalid scope: {0}")]
    InvalidScope(#[from] FromObjectScopeError),
}

pub struct BlueprintScope;

impl BlueprintScope {
    pub fn from_object_scope(scope: ObjectScope) -> Result<BlueprintScope, FromObjectScopeError> {
        match scope {
            ObjectScope::Blueprints => Ok(BlueprintScope),
            v => Err(FromObjectScopeError::InvalidScope("blueprint", v)),
        }
    }

    pub fn to_object_scope(&self) -> ObjectScope {
        ObjectScope::Blueprints
    }
}

define_object!(Blueprint, BlueprintFolder, BlueprintScope, BlueprintError);

impl Blueprint {
    #[instrument(level = Level::INFO, skip(conn, name, information), fields(name = name.as_ref()))]
    pub fn new(
        conn: Rc<Connection>,
        parent_folder: Option<&BlueprintFolder>,
        position: FolderPosition,
        name: impl AsRef<str>,
        information: impl AsRef<str>,
    ) -> Result<Self, BlueprintError> {
        validate_string_not_blank(&name)?;

        let blueprint = conn.transaction_rc(|conn| {
            let id = object_create(
                conn.clone(),
                ObjectType::Blueprint,
                ObjectScope::Blueprints,
                parent_folder.map(|v| v.to_folder()),
                position,
                name,
                information,
            )
            .map_err(|e| DbError::TransactionError(e.to_string()))?;

            conn.execute("INSERT INTO `blueprints`(`id`) VALUES(?)", id)?;

            Ok(Blueprint {
                conn: Rc::downgrade(&conn),
                id,
            })
        })?;

        Ok(blueprint)
    }
}