diff options
| author | Mikkel Thestrup <mikkel@mithe.dk> | 2026-01-26 21:27:59 +0100 |
|---|---|---|
| committer | Mikkel Thestrup <mikkel@mithe.dk> | 2026-01-27 15:37:03 +0100 |
| commit | 4e78fd83349c95711cdee5acc56f248f81ebd25c (patch) | |
| tree | 6a380da4c3651f73a806cafc9222012af9564f56 /src/domain/repository.rs | |
| parent | 4b1074193991a510fd2129513d5fcb7c6da933d2 (diff) | |
| download | kal-4e78fd83349c95711cdee5acc56f248f81ebd25c.tar.gz kal-4e78fd83349c95711cdee5acc56f248f81ebd25c.zip | |
feat(domain): add core domain models for calendar application
Implement domain-driven design layer with entities, value objects, and
repository traits for calendar management system.
Domain Entities:
- Calendar: manages calendar lifecycle and archival state
- Event: handles single occurrence events with cancellation support
- RecurringEvent: supports recurring events with exception handling
- RecurrenceException: manages modifications to specific occurrences
Value Objects:
- TimeRange: enforces valid start/end time constraints
- EventColor: type-safe color representation
- Frequency: recurrence frequency enumeration (daily/weekly/monthly/yearly)
- RecurrenceRule: encapsulates recurrence pattern logic
- CalendarId & EventId: essentially just a wrapper
Repository Traits:
- CalendarRepository: calendar persistence interface
- EventRepository: event querying and persistence with overlap detection
- RecurrenceRepository: recurring event management
Key Design Decisions:
- Use Uuid for entity IDs (type safety, performance)
- Encapsulate business logic within entities
- Immutable value objects with validation
- Repository pattern for infrastructure abstraction
- Clear separation of concerns between domain and persistence layers
All entities include timestamp tracking and follow builder pattern for
construction with validation at domain boundaries.
Diffstat (limited to '')
| -rw-r--r-- | src/domain/repository.rs | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/domain/repository.rs b/src/domain/repository.rs new file mode 100644 index 0000000..00b3974 --- /dev/null +++ b/src/domain/repository.rs @@ -0,0 +1,45 @@ +use async_trait::async_trait; +use super::{ + calendar::Calendar, + event::Event, + recurrence::RecurringEvent, + value_objects::{CalendarId, EventId, TimeRange}, +}; + +pub type Result<T> = std::result::Result<T, RepositoryError>; + +#[derive(Debug, thiserror::Error)] +pub enum RepositoryError { + #[error("Entity not found")] + NotFound, + + #[error("Database error: {0}")] + DatabaseError(String), + + #[error("Constraint violation: {0}")] + ConstraintViolation(String), +} + +#[async_trait] +pub trait CalendarRepository: Send + Sync { + async fn save(&self, calendar: &Calendar) -> Result<()>; + async fn find_by_id(&self, id: &CalendarId) -> Result<Option<Calendar>>; + async fn find_all_active(&self) -> Result<Vec<Calendar>>; + async fn delete(&self, id: &CalendarId) -> Result<()>; +} + +#[async_trait] +pub trait EventRepository: Send + Sync { + async fn save(&self, event: &Event) -> Result<()>; + async fn find_by_id(&self, id: &EventId) -> Result<Option<Event>>; + async fn find_by_calendar(&self, calendar_id: &CalendarId) -> Result<Vec<Event>>; + async fn find_in_range(&self, calendar_id: &CalendarId, range: &TimeRange) -> Result<Vec<Event>>; + async fn delete(&self, id: &EventId) -> Result<()>; +} + +#[async_trait] +pub trait RecurringEventRepository: Send + Sync { + async fn save(&self, event: &RecurringEvent) -> Result<()>; + async fn find_by_calendar(&self, calendar_id: &CalendarId) -> Result<Vec<RecurringEvent>>; + async fn delete(&self, id: &str) -> Result<()>; +} |