via-cli 0.2.0

Run commands and API requests with 1Password-backed credentials without exposing secrets to your shell
Documentation
use crate::config::{CommandConfig, Config};
use crate::error::ViaError;
use crate::providers::ProviderRegistry;

mod delegated;
mod rest;

pub fn invoke(
    config: &Config,
    providers: &ProviderRegistry,
    service_name: &str,
    capability_name: &str,
    args: Vec<String>,
) -> Result<(), ViaError> {
    let service = config
        .services
        .get(service_name)
        .ok_or_else(|| ViaError::UnknownService(service_name.to_owned()))?;
    let command =
        service
            .commands
            .get(capability_name)
            .ok_or_else(|| ViaError::UnknownCapability {
                service: service_name.to_owned(),
                capability: capability_name.to_owned(),
            })?;
    let provider = providers.get(&service.provider)?;

    match command {
        CommandConfig::Rest(rest) => rest::execute(service_name, service, rest, provider, args),
        CommandConfig::Delegated(delegated) => {
            delegated::execute(service_name, service, delegated, provider, args)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn config() -> Config {
        Config::from_toml_str(
            r#"
version = 1

[providers.onepassword]
type = "1password"

[services.github]
provider = "onepassword"

[services.github.secrets]
token = "op://Private/GitHub/token"

[services.github.commands.api]
mode = "rest"
base_url = "https://api.github.com"
"#,
        )
        .unwrap()
    }

    #[test]
    fn invoke_rejects_unknown_service() {
        let config = config();
        let providers = ProviderRegistry::from_config(&config).unwrap();
        let error = invoke(&config, &providers, "missing", "api", Vec::new()).unwrap_err();

        assert!(matches!(error, ViaError::UnknownService(service) if service == "missing"));
    }

    #[test]
    fn invoke_rejects_unknown_capability() {
        let config = config();
        let providers = ProviderRegistry::from_config(&config).unwrap();
        let error = invoke(&config, &providers, "github", "missing", Vec::new()).unwrap_err();

        assert!(matches!(
            error,
            ViaError::UnknownCapability {
                service,
                capability
            } if service == "github" && capability == "missing"
        ));
    }
}