init
This commit is contained in:
133
notes-domain/src/errors.rs
Normal file
133
notes-domain/src/errors.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
//! Domain errors for K-Notes
|
||||
//!
|
||||
//! Uses `thiserror` for ergonomic error definitions.
|
||||
//! These errors represent domain-level failures and will be mapped
|
||||
//! to HTTP status codes in the API layer.
|
||||
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::entities::MAX_TAGS_PER_NOTE;
|
||||
|
||||
/// Domain-level errors for K-Notes operations
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DomainError {
|
||||
/// The requested note was not found
|
||||
#[error("Note not found: {0}")]
|
||||
NoteNotFound(Uuid),
|
||||
|
||||
/// The requested user was not found
|
||||
#[error("User not found: {0}")]
|
||||
UserNotFound(Uuid),
|
||||
|
||||
/// The requested tag was not found
|
||||
#[error("Tag not found: {0}")]
|
||||
TagNotFound(Uuid),
|
||||
|
||||
/// User with this email/subject already exists
|
||||
#[error("User already exists: {0}")]
|
||||
UserAlreadyExists(String),
|
||||
|
||||
/// Tag with this name already exists for the user
|
||||
#[error("Tag already exists: {0}")]
|
||||
TagAlreadyExists(String),
|
||||
|
||||
/// Attempted to add too many tags to a note
|
||||
#[error("Tag limit exceeded: maximum {max} tags allowed, note has {current}")]
|
||||
TagLimitExceeded { max: usize, current: usize },
|
||||
|
||||
/// A validation error occurred
|
||||
#[error("Validation error: {0}")]
|
||||
ValidationError(String),
|
||||
|
||||
/// User is not authorized to perform this action
|
||||
#[error("Unauthorized: {0}")]
|
||||
Unauthorized(String),
|
||||
|
||||
/// A repository/infrastructure error occurred
|
||||
#[error("Repository error: {0}")]
|
||||
RepositoryError(String),
|
||||
}
|
||||
|
||||
impl DomainError {
|
||||
/// Create a tag limit exceeded error with the current count
|
||||
pub fn tag_limit_exceeded(current: usize) -> Self {
|
||||
Self::TagLimitExceeded {
|
||||
max: MAX_TAGS_PER_NOTE,
|
||||
current,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a validation error
|
||||
pub fn validation(message: impl Into<String>) -> Self {
|
||||
Self::ValidationError(message.into())
|
||||
}
|
||||
|
||||
/// Create an unauthorized error
|
||||
pub fn unauthorized(message: impl Into<String>) -> Self {
|
||||
Self::Unauthorized(message.into())
|
||||
}
|
||||
|
||||
/// Check if this error indicates a "not found" condition
|
||||
pub fn is_not_found(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
DomainError::NoteNotFound(_)
|
||||
| DomainError::UserNotFound(_)
|
||||
| DomainError::TagNotFound(_)
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if this error indicates a conflict (already exists)
|
||||
pub fn is_conflict(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
DomainError::UserAlreadyExists(_) | DomainError::TagAlreadyExists(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Result type alias for domain operations
|
||||
pub type DomainResult<T> = Result<T, DomainError>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_tag_limit_exceeded_uses_constant() {
|
||||
let error = DomainError::tag_limit_exceeded(15);
|
||||
|
||||
if let DomainError::TagLimitExceeded { max, current } = error {
|
||||
assert_eq!(max, MAX_TAGS_PER_NOTE);
|
||||
assert_eq!(current, 15);
|
||||
} else {
|
||||
panic!("Expected TagLimitExceeded error");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_display_messages() {
|
||||
let note_id = Uuid::new_v4();
|
||||
let error = DomainError::NoteNotFound(note_id);
|
||||
assert!(error.to_string().contains(¬e_id.to_string()));
|
||||
|
||||
let error = DomainError::validation("Title cannot be empty");
|
||||
assert_eq!(error.to_string(), "Validation error: Title cannot be empty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_not_found() {
|
||||
assert!(DomainError::NoteNotFound(Uuid::new_v4()).is_not_found());
|
||||
assert!(DomainError::UserNotFound(Uuid::new_v4()).is_not_found());
|
||||
assert!(DomainError::TagNotFound(Uuid::new_v4()).is_not_found());
|
||||
assert!(!DomainError::validation("test").is_not_found());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_conflict() {
|
||||
assert!(DomainError::UserAlreadyExists("test@example.com".into()).is_conflict());
|
||||
assert!(DomainError::TagAlreadyExists("work".into()).is_conflict());
|
||||
assert!(!DomainError::NoteNotFound(Uuid::new_v4()).is_conflict());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user