feat: add main features
Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
6
crates/application/src/remote/mod.rs
Normal file
6
crates/application/src/remote/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
//! Remote use cases (ARCHITECTURE §6, L9). Connecting a project's
|
||||
//! [`domain::ports::RemoteHost`] (local / SSH / WSL) and validating its root.
|
||||
|
||||
mod usecases;
|
||||
|
||||
pub use usecases::{ConnectRemote, ConnectRemoteInput, ConnectRemoteOutput};
|
||||
75
crates/application/src/remote/usecases.rs
Normal file
75
crates/application/src/remote/usecases.rs
Normal file
@ -0,0 +1,75 @@
|
||||
//! Remote-connection use case (ARCHITECTURE §6, L9).
|
||||
//!
|
||||
//! [`ConnectRemote`] establishes a project's [`RemoteHost`] and validates that
|
||||
//! its root is reachable on the host's filesystem. It speaks only to the
|
||||
//! [`RemoteHost`] port, so it behaves identically for a local, SSH or WSL host
|
||||
//! (Liskov) and is fully testable with a mock host.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::ports::{EventBus, RemoteHost, RemotePath};
|
||||
use domain::{DomainEvent, ProjectId, RemoteKind};
|
||||
|
||||
use crate::error::AppError;
|
||||
|
||||
/// Input for [`ConnectRemote::execute`].
|
||||
#[derive(Clone)]
|
||||
pub struct ConnectRemoteInput {
|
||||
/// The host strategy to connect through (built from the project's `RemoteRef`).
|
||||
pub host: Arc<dyn RemoteHost>,
|
||||
/// The project being connected (for the emitted event).
|
||||
pub project_id: ProjectId,
|
||||
/// Absolute root path to validate on the host.
|
||||
pub root: String,
|
||||
}
|
||||
|
||||
/// Output of [`ConnectRemote::execute`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ConnectRemoteOutput {
|
||||
/// The kind of host that was connected.
|
||||
pub kind: RemoteKind,
|
||||
}
|
||||
|
||||
/// Connects a project's remote host and checks its root is reachable.
|
||||
pub struct ConnectRemote {
|
||||
events: Arc<dyn EventBus>,
|
||||
}
|
||||
|
||||
impl ConnectRemote {
|
||||
/// Builds the use case from the [`EventBus`].
|
||||
#[must_use]
|
||||
pub fn new(events: Arc<dyn EventBus>) -> Self {
|
||||
Self { events }
|
||||
}
|
||||
|
||||
/// Connects the host and validates the root exists, announcing
|
||||
/// [`DomainEvent::RemoteConnected`] on success.
|
||||
///
|
||||
/// # Errors
|
||||
/// - [`AppError::Remote`] if the connection fails,
|
||||
/// - [`AppError::NotFound`] if the root does not exist on the host,
|
||||
/// - [`AppError::FileSystem`] on an I/O failure while probing the root.
|
||||
pub async fn execute(
|
||||
&self,
|
||||
input: ConnectRemoteInput,
|
||||
) -> Result<ConnectRemoteOutput, AppError> {
|
||||
input.host.connect().await?;
|
||||
|
||||
let fs = input.host.file_system();
|
||||
let exists = fs.exists(&RemotePath::new(input.root.clone())).await?;
|
||||
if !exists {
|
||||
return Err(AppError::NotFound(format!(
|
||||
"remote root {} is not reachable",
|
||||
input.root
|
||||
)));
|
||||
}
|
||||
|
||||
self.events.publish(DomainEvent::RemoteConnected {
|
||||
project_id: input.project_id,
|
||||
});
|
||||
|
||||
Ok(ConnectRemoteOutput {
|
||||
kind: input.host.kind(),
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user