sylphx-cli 0.2.5

Sylphx Platform CLI — dogfoods the Rust Management SDK
//! Human output + actionable error mapping for the operator CLI.

use serde::Serialize;
use sylphx_sdk_core::SdkError;

pub fn print_out<T: Serialize>(json: bool, value: &T, human: impl FnOnce()) {
    if json {
        println!(
            "{}",
            serde_json::to_string_pretty(value).unwrap_or_else(|_| "{}".into())
        );
    } else {
        human();
    }
}

pub fn emit_json_or<T: Serialize>(
    json: bool,
    value: &T,
    human: impl FnOnce(),
) -> anyhow::Result<()> {
    print_out(json, value, human);
    Ok(())
}

/// Map SDK errors into operator-actionable anyhow errors.
pub fn map_sdk_err(err: SdkError) -> anyhow::Error {
    match &err {
        SdkError::Api {
            status: 404,
            code,
            message,
        } if message.contains("/whoami") || message.contains("\"path\":\"/whoami\"") => {
            anyhow::anyhow!(
                "api 404: {code}: Management whoami route not found.\n\
                 \n\
                 Likely cause: API base URL is missing `/v1`\n\
                   wrong:  https://api.sylphx.com/whoami\n\
                   right:  https://api.sylphx.com/v1/whoami\n\
                 \n\
                 Fix:\n\
                   • sylphx doctor\n\
                   • sylphx login --token \"$SYLPHX_TOKEN\" --api-url https://api.sylphx.com/v1\n\
                   • or: export SYLPHX_API_URL=https://api.sylphx.com/v1\n\
                 \n\
                 Raw: {message}"
            )
        }
        SdkError::Api {
            status: 403,
            code,
            message,
        } if message.contains("user_context_required") => anyhow::anyhow!(
            "api 403: {code}: this endpoint needs a user-scoped credential.\n\
             \n\
             You are likely using a service token (`svc_*`).\n\
               • whoami / user profile → use `sylphx login` (device flow)\n\
               • deploy / projects / automation → `svc_*` is correct\n\
             \n\
             Raw: {message}"
        ),
        SdkError::Api {
            status: 401,
            code,
            message,
        } => anyhow::anyhow!(
            "api 401: {code}: not authenticated.\n\
             \n\
             Fix:\n\
               • sylphx login\n\
               • sylphx login --token svc_…\n\
               • export SYLPHX_TOKEN=…\n\
             \n\
             Then: sylphx doctor\n\
             Raw: {message}"
        ),
        SdkError::Api {
            status: 404,
            code,
            message,
        } => anyhow::anyhow!(
            "api 404: {code}: resource not found.\n\
             \n\
             Check:\n\
               • project/org id spelling\n\
               • preferred org (`sylphx context show` / `--org-id`)\n\
               • sylphx doctor\n\
             \n\
             Raw: {message}"
        ),
        other => anyhow::anyhow!("{other}"),
    }
}

pub fn ok_line(msg: &str) {
    println!("{msg}");
}