Transform the single binary crate into a 9-crate workspace monorepo: - Root Cargo.toml as [workspace] manager with resolver = "2" - zesdex-entities: Domain entity types (session, settings, store, message, etc.) - zesdex-utils: Pure utility functions (error, logger, pagination, slug, clipboard) - zesdex-dto: Data Transfer Objects for LLM provider API communication - zesdex-ipc: Unix-socket IPC layer (client/server/framing/protocol) - zesdex-iam: Identity & Access Management (Clean Architecture: domain/application/infrastructure) - zesdex-cms: Content Management (Clean Architecture: domain/application/infrastructure) - zesdex-middleware: HTTP middleware (Auth, CORS, Rate Limiting) - zesdex-libs: Composition root (AppContext, DB init, JWT, Argon2) - zesdex-backend: Main binary entry point + seed/migrate binaries - DevOps: Dockerfile, docker-compose, Nix (flake/shell/default), CI/CD updates - Remove dead root src/ and src-misc/ directories All crate re-exports maintain backward compatibility with original crate::model::*, crate::dto::*, crate::ipc::* module paths. Feature crates enforce strict layer separation: domain -> application -> infrastructure with generic trait-based dependency injection.
60 lines
1.8 KiB
Rust
60 lines
1.8 KiB
Rust
//! Shallow state diffing — records opaque "modified" markers so the TUI
|
|
//! knows to re-render without computing fine-grained deltas.
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// A collection of changes tracking which parts of app state have been
|
|
/// modified since the last render sweep.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct StateDiff {
|
|
changes: Vec<Change>,
|
|
}
|
|
|
|
/// A single named change — currently always carries a flat `"."` path
|
|
/// and `"modified"` kind because the system does not track granular diffs.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Change {
|
|
pub path: String,
|
|
pub kind: String,
|
|
}
|
|
|
|
impl StateDiff {
|
|
/// Create an empty diff.
|
|
pub fn new() -> Self {
|
|
StateDiff { changes: Vec::new() }
|
|
}
|
|
|
|
/// Record a change at `path` of the given `kind`.
|
|
pub fn add_change(&mut self, path: String, kind: String) {
|
|
self.changes.push(Change { path, kind });
|
|
}
|
|
|
|
/// Return true if no changes have been recorded.
|
|
pub fn is_empty(&self) -> bool {
|
|
self.changes.is_empty()
|
|
}
|
|
|
|
/// Remove all recorded changes.
|
|
pub fn clear(&mut self) {
|
|
self.changes.clear();
|
|
}
|
|
}
|
|
|
|
/// Compute a shallow diff between two serialised state values.
|
|
///
|
|
/// Flow: compare with `==`, return an empty vec if equal, otherwise
|
|
/// return a single `Change { ".", "modified" }`.
|
|
///
|
|
/// Why: a placeholder — the current rendering model re-validates the
|
|
/// whole viewport every frame, so fine-grained diffs are unnecessary.
|
|
///
|
|
/// Return: the list of changes (always 0 or 1 entry).
|
|
pub fn compute_diff(before: &serde_json::Value, after: &serde_json::Value) -> Vec<Change> {
|
|
if before == after {
|
|
return Vec::new();
|
|
}
|
|
vec![Change {
|
|
path: ".".to_string(),
|
|
kind: "modified".to_string(),
|
|
}]
|
|
}
|