feat: complete CLI milestone
Finish the Milestone 4 CLI surface with config management, daemon install and uninstall helpers, config reload handling, and final polish for secret redaction and running-socket tracking.
This commit is contained in:
+80
-5
@@ -6,7 +6,10 @@ use serde::{Deserialize, Serialize};
|
||||
use tokio::fs;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::adapters::{Device, DeviceInfo, TvAdapter, roku::RokuAdapter};
|
||||
use crate::{
|
||||
adapters::{AppInfo, Device, DeviceInfo, DeviceState, TvAdapter, TvKey, roku::RokuAdapter},
|
||||
daemon::config::TvctlConfig,
|
||||
};
|
||||
|
||||
/// The persisted collection of known devices.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -187,6 +190,17 @@ impl Default for AdapterRegistry {
|
||||
}
|
||||
|
||||
impl AdapterRegistry {
|
||||
/// Build the adapter registry from the loaded daemon config.
|
||||
pub fn from_config(config: &TvctlConfig) -> Self {
|
||||
let username =
|
||||
(!config.dev.roku_username.is_empty()).then(|| config.dev.roku_username.clone());
|
||||
let password =
|
||||
(!config.dev.roku_password.is_empty()).then(|| config.dev.roku_password.clone());
|
||||
Self {
|
||||
roku: RokuAdapter::with_dev_credentials(username, password),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the supported platform names.
|
||||
pub fn supported_platforms(&self) -> Vec<&'static str> {
|
||||
vec!["roku"]
|
||||
@@ -222,15 +236,76 @@ impl AdapterRegistry {
|
||||
}
|
||||
|
||||
/// Return apps from a concrete device using its platform adapter.
|
||||
pub async fn list_apps(
|
||||
&self,
|
||||
device: &Device,
|
||||
) -> anyhow::Result<Vec<crate::adapters::AppInfo>> {
|
||||
pub async fn list_apps(&self, device: &Device) -> anyhow::Result<Vec<AppInfo>> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.list_apps(device).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch the current state for a concrete device.
|
||||
pub async fn state(&self, device: &Device) -> anyhow::Result<DeviceState> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.state(device).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Launch an app on a concrete device.
|
||||
pub async fn launch(&self, device: &Device, app: &str) -> anyhow::Result<()> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.launch(device, app).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Stop the currently running app on a concrete device.
|
||||
pub async fn stop_app(&self, device: &Device) -> anyhow::Result<()> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.stop_app(device).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a single normalized key to a concrete device.
|
||||
pub async fn key(&self, device: &Device, key: TvKey) -> anyhow::Result<()> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.key(device, key).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a normalized key sequence to a concrete device.
|
||||
pub async fn sequence(&self, device: &Device, keys: Vec<TvKey>) -> anyhow::Result<()> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.sequence(device, keys).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Install a development package on a concrete device.
|
||||
pub async fn dev_install(&self, device: &Device, zip: &[u8]) -> anyhow::Result<()> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.dev_install(device, zip).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reload the active development package on a concrete device.
|
||||
pub async fn dev_reload(&self, device: &Device) -> anyhow::Result<()> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.dev_reload(device).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch development logs from a concrete device.
|
||||
pub async fn dev_logs(&self, device: &Device) -> anyhow::Result<Vec<String>> {
|
||||
match device.platform.as_str() {
|
||||
"roku" => Ok(self.roku.dev_logs(device).await?),
|
||||
other => anyhow::bail!("unsupported platform '{other}'"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_target(device: &Device, target: &str) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user