aboutsummaryrefslogtreecommitdiff
path: root/src/domain/repository.rs
diff options
context:
space:
mode:
authorMikkel Thestrup <mikkel@mithe.dk>2026-01-26 21:27:59 +0100
committerMikkel Thestrup <mikkel@mithe.dk>2026-01-27 15:37:03 +0100
commit4e78fd83349c95711cdee5acc56f248f81ebd25c (patch)
tree6a380da4c3651f73a806cafc9222012af9564f56 /src/domain/repository.rs
parent4b1074193991a510fd2129513d5fcb7c6da933d2 (diff)
downloadkal-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.rs45
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<()>;
+}