naps 1.0.0

NATS server proxy service to relay and forward custom topics and subjects
Documentation
use std::path::Path;

use anyhow::Context;
use async_nats::ConnectOptions;

use crate::config::{Auth, Connection};

pub async fn connect(conn: &Connection, name: &str) -> anyhow::Result<async_nats::Client> {
    let url = &conn.url;
    connect_inner(conn, name)
        .await
        .with_context(|| format!("connect {name} to {url}"))
}

async fn connect_inner(conn: &Connection, name: &str) -> anyhow::Result<async_nats::Client> {
    let mut opts = match &conn.auth {
        Some(Auth::CredsFile(path)) => ConnectOptions::with_credentials_file(path).await?,
        _ => ConnectOptions::new(),
    }
    .name(name);

    if let Some(tls) = &conn.tls {
        opts = opts.require_tls(true);
        if let Some(ca_file) = &tls.ca_file {
            opts = opts.add_root_certificates(ca_file.clone());
        }
        if let (Some(cert_file), Some(key_file)) = (&tls.cert_file, &tls.key_file) {
            opts = opts.add_client_certificate(cert_file.clone(), key_file.clone());
        }
    }

    match &conn.auth {
        Some(Auth::NkeyFile(path)) => opts = opts.nkey(read_trimmed(path)?),
        Some(Auth::TokenFile(path)) => opts = opts.token(read_trimmed(path)?),
        Some(Auth::CredsFile(_)) | None => {}
    }

    Ok(opts.connect(&conn.url).await?)
}

fn read_trimmed(path: &Path) -> anyhow::Result<String> {
    let content =
        std::fs::read_to_string(path).with_context(|| format!("read {}", path.display()))?;
    Ok(content.trim().to_string())
}