//! Presentation layer - API contracts and DTOs //! //! This module defines data transfer objects (DTOs) and API request/response types //! that form the public API contract. It translates between domain types and wire //! formats (JSON) for HTTP communication. //! //! # Current Status //! //! **Currently unused** - API handlers are currently in [`crate::route`] module using //! legacy structure. This module is prepared for future migration to proper hexagonal //! architecture with clear presentation layer separation. //! //! # Architecture Principles //! //! - **API-first design**: Define contracts before implementation //! - **DTO pattern**: Separate domain entities from API representations //! - **Validation at boundary**: Parse and validate input before domain layer //! - **OpenAPI integration**: Generate documentation from code //! //! # Planned Submodules //! //! ## `dto` - Data Transfer Objects //! //! - `relay_dto`: RelayResponse, RelayStatusResponse, BulkControlRequest //! - `label_dto`: UpdateLabelRequest, LabelResponse //! - `health_dto`: HealthResponse, DeviceStatusResponse //! - `error_dto`: ApiError, ValidationError (user-facing errors) //! //! ## `mapper` - Domain ↔ DTO Conversions //! //! - `relay_mapper`: Convert between Relay entity and RelayResponse //! - `error_mapper`: Translate domain errors to HTTP status codes //! //! ## `validator` - Input Validation //! //! - Request validation before domain layer //! - Parse DTOs into domain types (parse, don't validate principle) //! //! # DTO Design Pattern //! //! DTOs are separate from domain types to: //! 1. **Prevent domain leakage**: Domain types stay internal //! 2. **Enable versioning**: API can evolve without changing domain //! 3. **Control serialization**: Explicit JSON representation //! 4. **Validate at boundary**: Convert raw input to validated domain types //! //! # Example DTO Structure //! //! ```rust,ignore //! /// API response for relay status //! #[derive(Serialize, Deserialize, Object)] //! pub struct RelayResponse { //! /// Relay ID (1-8) //! pub id: u8, //! /// Current state ("on" or "off") //! pub state: String, //! /// Optional custom label //! pub label: Option, //! } //! //! impl From for RelayResponse { //! fn from(relay: Relay) -> Self { //! Self { //! id: relay.id().value(), //! state: relay.state().to_string(), //! label: relay.label().map(|l| l.to_string()), //! } //! } //! } //! //! impl TryFrom for Relay { //! type Error = ValidationError; //! //! fn try_from(dto: RelayResponse) -> Result { //! let id = RelayId::new(dto.id)?; //! let state = RelayState::from_str(&dto.state)?; //! let label = dto.label.map(RelayLabel::new).transpose()?; //! Ok(Relay::new(id, state).with_label(label)) //! } //! } //! ``` //! //! # Migration Plan //! //! Current API in [`crate::route`] will be migrated to this layer: //! 1. Define DTOs for all API endpoints //! 2. Implement domain � DTO mappers //! 3. Move API handlers to use DTOs //! 4. Generate OpenAPI specs from DTOs //! 5. Remove direct domain type exposure //! //! # References //! //! - Architecture: `specs/constitution.md` - API-First Design principle //! - API design: `specs/001-modbus-relay-control/plan.md` - Presentation layer tasks //! - Domain types: [`crate::domain`] - Types to be wrapped in DTOs /// Data Transfer Objects (DTOs) for API responses. /// /// This module contains DTO structures that are used to serialize domain /// objects for API responses, providing a clean separation between internal /// domain models and external API contracts. pub mod api; pub mod dto; pub mod error;