add config-sqlite and http-api adapters

SQLite config store: full ConfigRepository impl with JSON serialization
for mappings, layouts, data source configs. 12 integration tests.

HTTP API: Axum REST endpoints for widgets, data sources, layout, presets.
6 integration tests using tower::oneshot.

Port traits updated to return Send futures for Axum compatibility.
This commit is contained in:
2026-06-18 22:47:38 +02:00
parent 3ee6a5d215
commit e398c240a0
16 changed files with 3284 additions and 50 deletions

View File

@@ -1,17 +1,18 @@
use std::future::Future;
use crate::entities::WidgetId;
use crate::value_objects::{Layout, WidgetState};
pub trait BroadcastPort {
type Error;
async fn push_screen_update(
fn push_screen_update(
&self,
layout: &Layout,
widgets: &[(WidgetId, WidgetState)],
) -> Result<(), Self::Error>;
) -> impl Future<Output = Result<(), Self::Error>> + Send;
async fn push_data_update(
fn push_data_update(
&self,
updates: &[(WidgetId, WidgetState)],
) -> Result<(), Self::Error>;
) -> impl Future<Output = Result<(), Self::Error>> + Send;
}

View File

@@ -1,3 +1,4 @@
use std::future::Future;
use crate::entities::{
DataSource, DataSourceId, LayoutPreset, LayoutPresetId, WidgetConfig, WidgetId,
};
@@ -6,21 +7,21 @@ use crate::value_objects::Layout;
pub trait ConfigRepository {
type Error;
async fn get_widget(&self, id: WidgetId) -> Result<Option<WidgetConfig>, Self::Error>;
async fn list_widgets(&self) -> Result<Vec<WidgetConfig>, Self::Error>;
async fn save_widget(&self, config: &WidgetConfig) -> Result<(), Self::Error>;
async fn delete_widget(&self, id: WidgetId) -> Result<(), Self::Error>;
fn get_widget(&self, id: WidgetId) -> impl Future<Output = Result<Option<WidgetConfig>, Self::Error>> + Send;
fn list_widgets(&self) -> impl Future<Output = Result<Vec<WidgetConfig>, Self::Error>> + Send;
fn save_widget(&self, config: &WidgetConfig) -> impl Future<Output = Result<(), Self::Error>> + Send;
fn delete_widget(&self, id: WidgetId) -> impl Future<Output = Result<(), Self::Error>> + Send;
async fn get_data_source(&self, id: DataSourceId) -> Result<Option<DataSource>, Self::Error>;
async fn list_data_sources(&self) -> Result<Vec<DataSource>, Self::Error>;
async fn save_data_source(&self, source: &DataSource) -> Result<(), Self::Error>;
async fn delete_data_source(&self, id: DataSourceId) -> Result<(), Self::Error>;
fn get_data_source(&self, id: DataSourceId) -> impl Future<Output = Result<Option<DataSource>, Self::Error>> + Send;
fn list_data_sources(&self) -> impl Future<Output = Result<Vec<DataSource>, Self::Error>> + Send;
fn save_data_source(&self, source: &DataSource) -> impl Future<Output = Result<(), Self::Error>> + Send;
fn delete_data_source(&self, id: DataSourceId) -> impl Future<Output = Result<(), Self::Error>> + Send;
async fn get_layout(&self) -> Result<Option<Layout>, Self::Error>;
async fn save_layout(&self, layout: &Layout) -> Result<(), Self::Error>;
fn get_layout(&self) -> impl Future<Output = Result<Option<Layout>, Self::Error>> + Send;
fn save_layout(&self, layout: &Layout) -> impl Future<Output = Result<(), Self::Error>> + Send;
async fn get_preset(&self, id: LayoutPresetId) -> Result<Option<LayoutPreset>, Self::Error>;
async fn list_presets(&self) -> Result<Vec<LayoutPreset>, Self::Error>;
async fn save_preset(&self, preset: &LayoutPreset) -> Result<(), Self::Error>;
async fn delete_preset(&self, id: LayoutPresetId) -> Result<(), Self::Error>;
fn get_preset(&self, id: LayoutPresetId) -> impl Future<Output = Result<Option<LayoutPreset>, Self::Error>> + Send;
fn list_presets(&self) -> impl Future<Output = Result<Vec<LayoutPreset>, Self::Error>> + Send;
fn save_preset(&self, preset: &LayoutPreset) -> impl Future<Output = Result<(), Self::Error>> + Send;
fn delete_preset(&self, id: LayoutPresetId) -> impl Future<Output = Result<(), Self::Error>> + Send;
}

View File

@@ -1,8 +1,9 @@
use std::future::Future;
use crate::entities::DataSource;
use crate::value_objects::Value;
pub trait DataSourcePort {
type Error;
async fn poll(&self, source: &DataSource) -> Result<Value, Self::Error>;
fn poll(&self, source: &DataSource) -> impl Future<Output = Result<Value, Self::Error>> + Send;
}

View File

@@ -1,7 +1,8 @@
use std::future::Future;
use crate::events::DomainEvent;
pub trait EventPublisher {
type Error;
async fn publish(&self, event: DomainEvent) -> Result<(), Self::Error>;
fn publish(&self, event: DomainEvent) -> impl Future<Output = Result<(), Self::Error>> + Send;
}