1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! Handler traits for REST CRUD patterns
//!
//! This module provides handler-level abstractions for the standard REST
//! collection pattern (list, get, create, update, delete). It builds on
//! the repository traits to provide HTTP-aware error handling and response types.
//!
//! # Features
//!
//! - **CRUD Handlers**: [`CollectionHandler`] trait for standard REST operations
//! - **Soft Delete**: [`SoftDeleteHandler`] for GDPR compliance and audit trails
//! - **Pagination**: [`ListQuery`] and [`ListResponse`] for paginated list endpoints
//! - **Error Handling**: [`ApiError`] with automatic HTTP status code mapping
//!
//! # Example
//!
//! ```rust,ignore
//! use acton_service::handlers::{
//! ApiError, CollectionHandler, ItemResponse, ListQuery, ListResponse, PaginationMeta,
//! };
//! use acton_service::repository::Repository;
//!
//! struct UserHandler {
//! repository: UserRepository,
//! }
//!
//! impl CollectionHandler<UserId, User, CreateUser, UpdateUser> for UserHandler {
//! async fn list(&self, query: ListQuery) -> Result<ListResponse<User>, ApiError> {
//! let filters = vec![];
//! let order = query.sort.as_ref().map(|s| (s.as_str(), query.sort_order().into()));
//! let pagination = Some(Pagination::new(query.offset(), query.items_per_page().into()));
//!
//! let users = self.repository.find_all(&filters, order, pagination).await?;
//! let total = self.repository.count(&filters).await?;
//!
//! Ok(ListResponse::new(users, PaginationMeta::new(
//! query.page_number(),
//! query.items_per_page(),
//! total,
//! )))
//! }
//!
//! async fn get(&self, id: &UserId) -> Result<ItemResponse<User>, ApiError> {
//! let user = self.repository.find_by_id(id).await?
//! .ok_or_else(|| ApiError::not_found("User", id.to_string()))?;
//! Ok(ItemResponse::new(user))
//! }
//!
//! async fn create(&self, dto: CreateUser) -> Result<ItemResponse<User>, ApiError> {
//! let user = self.repository.create(dto).await?;
//! Ok(ItemResponse::new(user))
//! }
//!
//! async fn update(&self, id: &UserId, dto: UpdateUser) -> Result<ItemResponse<User>, ApiError> {
//! let user = self.repository.update(id, dto).await?;
//! Ok(ItemResponse::new(user))
//! }
//!
//! async fn delete(&self, id: &UserId) -> Result<(), ApiError> {
//! self.repository.delete(id).await?;
//! Ok(())
//! }
//! }
//! ```
//!
//! # Integration with Axum
//!
//! The response types implement `IntoResponse`, so they can be returned directly
//! from Axum handlers:
//!
//! ```rust,ignore
//! use axum::{extract::{Path, Query, State}, Json};
//! use acton_service::handlers::{CollectionHandler, ListQuery};
//!
//! async fn list_users(
//! State(handler): State<UserHandler>,
//! Query(query): Query<ListQuery>,
//! ) -> Result<impl IntoResponse, ApiError> {
//! handler.list(query).await
//! }
//!
//! async fn get_user(
//! State(handler): State<UserHandler>,
//! Path(id): Path<UserId>,
//! ) -> Result<impl IntoResponse, ApiError> {
//! handler.get(&id).await
//! }
//! ```
// Re-export all public types
pub use ;
pub use ;
pub use ;
pub use ;