| Crates.io | kanban-core |
| lib.rs | kanban-core |
| version | 0.1.16 |
| created_at | 2025-10-12 22:13:02.122954+00 |
| updated_at | 2025-12-21 20:46:58.178811+00 |
| description | Core traits, errors, and result types for the kanban project management tool |
| homepage | https://github.com/fulsomenko/kanban |
| repository | https://github.com/fulsomenko/kanban |
| max_upload_size | |
| id | 1879786 |
| size | 27,753 |
Foundation crate providing core abstractions, error handling, and result types for the kanban workspace.
Add to your Cargo.toml:
[dependencies]
kanban-core = { path = "../kanban-core" }
pub type KanbanResult<T> = Result<T, KanbanError>;
Standard result type used throughout the workspace for consistent error handling.
KanbanError enum with variants:
Connection(String) - Connection/network errorsNotFound(String) - Resource not foundValidation(String) - Input validation failuresIo(std::io::Error) - File system and I/O errorsSerialization(String) - JSON/serde errorsInternal(String) - Unexpected internal errorsAppConfig - Cross-platform application configuration:
pub struct AppConfig {
pub default_sprint_prefix: Option<String>,
pub default_card_prefix: Option<String>,
}
impl AppConfig {
pub async fn load() -> KanbanResult<Self>
pub fn config_path() -> PathBuf
}
Loads from platform-specific paths:
~/.config/kanban/config.toml%APPDATA%\kanban\config.tomlLoggable trait for entities to maintain audit logs:
pub trait Loggable {
fn add_log(&mut self, entry: LogEntry);
fn get_logs(&self) -> &[LogEntry];
}
pub struct LogEntry {
pub timestamp: DateTime<Utc>,
pub message: String,
}
Editable Pattern - Safe entity modification via DTOs:
pub trait Editable<T>: Sized {
fn from_entity(entity: &T) -> Self;
fn apply_to(self, entity: &mut T) -> KanbanResult<()>;
}
Consuming crates implement Editable<Card>, Editable<Board>, etc. to provide type-safe updates with validation.
Repository Pattern - Generic async data access:
pub trait Repository<T, Id>: Send + Sync {
async fn find_by_id(&self, id: Id) -> KanbanResult<T>;
async fn find_all(&self) -> KanbanResult<Vec<T>>;
async fn save(&mut self, entity: T) -> KanbanResult<()>;
async fn delete(&mut self, id: Id) -> KanbanResult<()>;
}
Service Pattern - Business logic abstraction:
pub trait Service<T, Id>: Send + Sync {
async fn get(&self, id: Id) -> KanbanResult<T>;
async fn list(&self) -> KanbanResult<Vec<T>>;
async fn create(&mut self, entity: T) -> KanbanResult<Id>;
async fn update(&mut self, entity: T) -> KanbanResult<()>;
async fn delete(&mut self, id: Id) -> KanbanResult<()>;
}
Foundation layer with no workspace dependencies. All other crates depend on kanban-core for shared abstractions and error types.
kanban-core (foundation)
↑
└── kanban-domain, kanban-tui, kanban-cli
use kanban_core::{KanbanError, KanbanResult};
fn validate_name(name: &str) -> KanbanResult<()> {
if name.is_empty() {
return Err(KanbanError::Validation("Name cannot be empty".into()));
}
Ok(())
}
async fn fetch_data() -> KanbanResult<Vec<u8>> {
std::fs::read("data.json")
.map_err(|e| KanbanError::Io(e))
}
use kanban_core::AppConfig;
let config = AppConfig::load().await?;
let prefix = config.default_card_prefix.unwrap_or("task".into());
use kanban_core::Editable;
struct CardUpdate {
title: String,
priority: CardPriority,
}
impl Editable<Card> for CardUpdate {
fn from_entity(card: &Card) -> Self {
Self {
title: card.title.clone(),
priority: card.priority,
}
}
fn apply_to(self, card: &mut Card) -> KanbanResult<()> {
card.title = self.title;
card.priority = self.priority;
Ok(())
}
}
thiserror - Ergonomic error handling macrosanyhow - Context-aware error handlingserde, serde_json - Serialization frameworkuuid - UUID generation for IDschrono - Date and time typesasync-trait - Async trait method supporttoml - Configuration file parsingdirs - Cross-platform directory pathsApache 2.0 - See LICENSE.md for details