use std::time::Duration;
use serde::Serialize;
use crate::backend::command::stderr_snippet;
use crate::error::ComputerError;
use crate::protocol::APPLE_EVENT_TIMEOUT_SECS;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct ShortcutsReport {
pub exit_status: i32,
pub stderr: String,
}
pub fn run(name: &str) -> Result<ShortcutsReport, ComputerError> {
let trimmed = name.trim();
if trimmed.is_empty() {
return Err(ComputerError::InvalidArguments(
"shortcuts run requires a workflow name".into(),
));
}
let timeout = Duration::from_secs(APPLE_EVENT_TIMEOUT_SECS);
let output = crate::backend::command::run_timeout("shortcuts", &["run", trimmed], timeout)
.map_err(ComputerError::ExecutionFailed)?;
let exit_status = output.status.code().unwrap_or(-1);
let stderr = stderr_snippet(&output.stderr);
if !output.status.success() {
return Err(ComputerError::ExecutionFailed(format!(
"shortcuts run {trimmed} failed (exit {exit_status}): {stderr}"
)));
}
Ok(ShortcutsReport {
exit_status,
stderr,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_name_is_an_argument_error() {
let error = run("").unwrap_err();
assert!(matches!(error, ComputerError::InvalidArguments(_)));
}
#[test]
fn whitespace_name_is_an_argument_error() {
let error = run(" ").unwrap_err();
assert!(matches!(error, ComputerError::InvalidArguments(_)));
}
}