14 releases
| new 0.2.0 | Feb 1, 2026 |
|---|---|
| 0.1.16 | Dec 21, 2025 |
| 0.1.14 | Nov 17, 2025 |
| 0.1.10 | Oct 26, 2025 |
#503 in Development tools
Used in 4 crates
63KB
1.5K
SLoC
kanban-core
Foundation crate providing core abstractions, error handling, and result types for the kanban workspace.
Installation
Add to your Cargo.toml:
[dependencies]
kanban-core = { path = "../kanban-core" }
API Reference
Result Type
pub type KanbanResult<T> = Result<T, KanbanError>;
Standard result type used throughout the workspace for consistent error handling.
Errors
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 errorsConflictDetected { path, source }- File modified by another instanceCycleDetected- Adding an edge would create a circular dependencySelfReference- Self-referencing edge not allowedEdgeNotFound- Graph edge not found
Configuration
AppConfig - 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:
- macOS/Linux:
~/.config/kanban/config.toml - Windows:
%APPDATA%\kanban\config.toml
Logging
Loggable 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,
}
Traits
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<()>;
}
Graph
Generic directed graph (Graph<E>) for modeling relationships between entities. Used by kanban-domain for card dependencies. Edge types implement the Edge trait, which declares whether cycles are allowed — the graph enforces DAG constraints automatically for acyclic edge types.
State Primitives
UI-agnostic building blocks used by the TUI and available to any consumer:
InputState— Text input buffer with cursor tracking and multi-byte UTF-8 supportSelectionState— Single-item selection for navigable lists (next/prev, jump to first/last, clamp to bounds)Page/PageInfo— Viewport pagination that calculates visible items, scroll offset, and above/below counts
Architecture
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
Examples
Error Handling
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))
}
Configuration
use kanban_core::AppConfig;
let config = AppConfig::load().await?;
let prefix = config.default_card_prefix.unwrap_or("task".into());
Implementing Editable
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(())
}
}
Dependencies
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 paths
License
Apache 2.0 - See LICENSE.md for details
Dependencies
~2–13MB
~104K SLoC