zilliz 1.0.0

TUI and CLI tool for managing Zilliz Cloud clusters and Milvus operations
Documentation
use std::collections::HashMap;

use indexmap::IndexMap;
use serde::Deserialize;

/// Top-level CLI model, parsed from control-plane.json or data-plane.json.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
pub struct CliModel {
    #[serde(default)]
    pub version: String,
    #[serde(default)]
    pub min_cli_version: String,
    pub endpoint: Option<String>,
    pub auth: Option<AuthConfig>,
    #[serde(default)]
    pub resources: IndexMap<String, Resource>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct AuthConfig {
    #[serde(default, alias = "auth0Domain")]
    pub auth0_domain: String,
    #[serde(default, alias = "clientId")]
    pub client_id: String,
    #[serde(default, alias = "loginApi")]
    pub login_api: String,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Resource {
    pub description: Option<String>,
    #[serde(default)]
    pub dedicated_only: bool,
    #[serde(default)]
    pub operations: IndexMap<String, Operation>,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
pub struct Operation {
    #[serde(default)]
    pub http: HttpConfig,
    #[serde(default)]
    pub params: Vec<Param>,
    pub body_param: Option<String>,
    #[serde(default)]
    pub output: OutputConfig,
    pub pagination: Option<Pagination>,
    pub description: Option<String>,
    #[serde(default)]
    pub examples: Vec<String>,
    #[serde(default)]
    pub dedicated_only: bool,
    pub body_transform: Option<serde_json::Value>,
    #[serde(default)]
    pub body_defaults: serde_json::Map<String, serde_json::Value>,
}

impl Operation {
    pub fn method(&self) -> &str {
        &self.http.method
    }

    pub fn path(&self) -> &str {
        &self.http.path
    }
}

#[derive(Debug, Clone, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HttpConfig {
    #[serde(default = "default_method")]
    pub method: String,
    #[serde(default)]
    pub path: String,
}

fn default_method() -> String {
    "GET".to_string()
}

#[derive(Debug, Clone, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
pub struct OutputConfig {
    pub data_field: Option<String>,
    #[serde(default)]
    pub columns: Option<Vec<String>>,
    #[serde(default)]
    pub color_map: Option<HashMap<String, HashMap<String, String>>>,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
pub struct Param {
    pub name: String,
    #[serde(default = "default_type")]
    #[serde(rename = "type")]
    pub param_type: String,
    #[serde(rename = "cli")]
    pub cli_name: Option<String>,
    #[serde(default)]
    pub required: bool,
    pub default: Option<serde_json::Value>,
    pub position: Option<String>,
    pub required_unless: Option<String>,
    pub required_when: Option<serde_json::Value>,
    pub description: Option<String>,
    pub choices: Option<Vec<String>>,
    pub transform: Option<serde_json::Value>,
}

fn default_type() -> String {
    "string".to_string()
}

impl Param {
    /// Get the CLI flag name (e.g., "--cluster-id").
    pub fn cli_flag(&self) -> String {
        self.cli_name
            .clone()
            .unwrap_or_else(|| format!("--{}", self.name))
    }

    /// Whether this param goes in the URL path vs query/body.
    pub fn is_path_param(&self) -> bool {
        self.position.as_deref() == Some("path")
    }
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
pub struct Pagination {
    #[serde(default = "default_page_size_param")]
    pub page_size_param: String,
    #[serde(default = "default_page_param")]
    pub page_param: String,
    #[serde(default = "default_count_field")]
    pub count_field: String,
    #[serde(default = "default_data_field")]
    pub data_field: String,
    #[serde(default = "default_page_size")]
    pub default_page_size: u32,
}

fn default_page_size_param() -> String {
    "pageSize".to_string()
}
fn default_page_param() -> String {
    "currentPage".to_string()
}
fn default_count_field() -> String {
    "count".to_string()
}
fn default_data_field() -> String {
    "data".to_string()
}
fn default_page_size() -> u32 {
    100
}