dink-sdk 0.3.1

Rust SDK for Dink edge mesh platform — JSON-over-NATS RPC for IoT and edge computing
Documentation
use async_nats::Client;
use bytes::Bytes;
use std::time::Duration;

use crate::error::{DinkError, Result};

/// Send an authenticated request-reply to a NATS subject.
///
/// Uses `send_request` with a [`async_nats::Request`] to attach both
/// authorization headers and a per-request timeout.
pub async fn request_with_auth(
    client: &Client,
    subject: &str,
    data: &[u8],
    api_key: &str,
    timeout: Duration,
) -> Result<async_nats::Message> {
    let mut headers = async_nats::HeaderMap::new();
    headers.insert("Authorization", format!("Bearer {}", api_key).as_str());

    let request = async_nats::Request::new()
        .headers(headers)
        .payload(Bytes::copy_from_slice(data))
        .timeout(Some(timeout));

    client
        .send_request(subject.to_string(), request)
        .await
        .map_err(|e| DinkError::Nats(e.to_string()))
}

/// Send a plain (unauthenticated) request-reply.
pub async fn request(
    client: &Client,
    subject: &str,
    data: &[u8],
    timeout: Duration,
) -> Result<async_nats::Message> {
    let request = async_nats::Request::new()
        .payload(Bytes::copy_from_slice(data))
        .timeout(Some(timeout));

    client
        .send_request(subject.to_string(), request)
        .await
        .map_err(|e| DinkError::Nats(e.to_string()))
}

// ---------------------------------------------------------------------------
// Subject builders
// ---------------------------------------------------------------------------

/// `edge.{appId}.{edgeId}.services.{svc}.{method}`
pub fn edge_service_subject(app_id: &str, edge_id: &str, service: &str, method: &str) -> String {
    format!(
        "edge.{}.{}.services.{}.{}",
        app_id, edge_id, service, method
    )
}

/// `edge.{appId}.{edgeId}.services.{svc}.{method}.stream`
pub fn edge_service_stream_subject(
    app_id: &str,
    edge_id: &str,
    service: &str,
    method: &str,
) -> String {
    format!(
        "edge.{}.{}.services.{}.{}.stream",
        app_id, edge_id, service, method
    )
}

/// `edge.{appId}.{edgeId}.services.{svc}.>`
pub fn edge_service_wildcard(app_id: &str, edge_id: &str, service: &str) -> String {
    format!("edge.{}.{}.services.{}.>", app_id, edge_id, service)
}

/// `edge.{appId}.group.{groupId}.{edgeId}.services.{svc}.{method}`
pub fn peer_directed_subject(
    app_id: &str,
    group_id: &str,
    edge_id: &str,
    service: &str,
    method: &str,
) -> String {
    format!(
        "edge.{}.group.{}.{}.services.{}.{}",
        app_id, group_id, edge_id, service, method
    )
}

/// `edge.{appId}.group.{groupId}.services.{svc}.{method}`
pub fn peer_broadcast_subject(app_id: &str, group_id: &str, service: &str, method: &str) -> String {
    format!(
        "edge.{}.group.{}.services.{}.{}",
        app_id, group_id, service, method
    )
}

/// `edge.{appId}.group.{groupId}.{edgeId}.services.{svc}.>`
pub fn peer_directed_wildcard(
    app_id: &str,
    group_id: &str,
    edge_id: &str,
    service: &str,
) -> String {
    format!(
        "edge.{}.group.{}.{}.services.{}.>",
        app_id, group_id, edge_id, service
    )
}

/// `edge.{appId}.group.{groupId}.services.{svc}.>`
pub fn peer_broadcast_wildcard(app_id: &str, group_id: &str, service: &str) -> String {
    format!("edge.{}.group.{}.services.{}.>", app_id, group_id, service)
}

/// `center.{appId}.group.{groupId}.services.{svc}.{method}`
pub fn center_group_subject(app_id: &str, group_id: &str, service: &str, method: &str) -> String {
    format!(
        "center.{}.group.{}.services.{}.{}",
        app_id, group_id, service, method
    )
}