1use serde::{Deserialize, Serialize};
15use ferrox_errors::AppError;
16
17#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
20pub struct Pagination {
21 limit: u32,
22 offset: u32,
23}
24
25impl Pagination {
26 pub fn new(limit: u32, offset: u32) -> Result<Self, AppError> {
28 if limit == 0 {
29 return Err(AppError::ValidationError("Limit must be strictly greater than 0".into()));
30 }
31 if limit > 100 {
32 return Err(AppError::ValidationError("Limit cannot exceed 100".into()));
33 }
34
35 Ok(Self { limit, offset })
36 }
37
38 pub fn limit(&self) -> u32 {
39 self.limit
40 }
41
42 pub fn offset(&self) -> u32 {
43 self.offset
44 }
45}
46
47use validator::Validate;
48use ts_rs::TS;
49
50#[derive(Debug, Clone, Serialize, Deserialize, Validate, TS)]
53#[ts(export)]
54pub struct CreateUserDto {
55 #[validate(email)]
56 pub email: String,
57
58 #[validate(length(min = 8, message = "Password must be at least 8 characters"))]
59 pub password: String,
60
61 #[validate(range(min = 18, max = 130))]
62 pub age: u8,
63}
64
65pub fn setup() {
66 println!("ferrox-types initialized: Provides domain primitives and marker traits.");
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
75 fn test_pagination_validation_fails_on_zero_limit() {
76 let result = Pagination::new(0, 10);
77 assert!(result.is_err());
78 if let Err(AppError::ValidationError(msg)) = result {
79 assert_eq!(msg, "Limit must be strictly greater than 0");
80 } else {
81 panic!("Expected ValidationError");
82 }
83 }
84
85 #[test]
86 fn test_pagination_validation_fails_on_large_limit() {
87 let result = Pagination::new(101, 0);
88 assert!(result.is_err());
89 }
90
91 #[test]
92 fn test_pagination_creation_success() {
93 let pagination = Pagination::new(50, 20).unwrap();
94 assert_eq!(pagination.limit(), 50);
95 assert_eq!(pagination.offset(), 20);
96 }
97
98 #[test]
99 fn test_dto_validation() {
100 let bad_dto = CreateUserDto {
101 email: "invalid_email".into(),
102 password: "short".into(),
103 age: 15, };
105
106 let result = bad_dto.validate();
107 assert!(result.is_err());
108 let errs = result.unwrap_err();
109
110 let err_map = errs.field_errors();
112 assert!(err_map.contains_key("email"));
113 assert!(err_map.contains_key("password"));
114 assert!(err_map.contains_key("age"));
115 }
116}