use anyhow::Result;
use clap::Args;
use serde_json::json;
use crate::commands::provision::{email_login_required, ensure_provisioned, ProvisionOptions};
use crate::config::CliConfig;
use crate::output;
#[derive(Args)]
pub struct SetupArgs {
#[arg(long, default_value = "My Offline App")]
pub app_name: String,
#[arg(long)]
pub org_name: Option<String>,
#[arg(long, default_value = "CLI default")]
pub key_alias: String,
#[arg(long, default_value = "all")]
pub product: String,
#[arg(long)]
pub json: bool,
}
pub async fn run(args: SetupArgs) -> Result<()> {
let mut config = CliConfig::load()?;
crate::commands::provision::ensure_logged_in_for_provision(&config, !args.json).await?;
config = CliConfig::load()?;
if !config.has_api_credentials() && config.effective_access_token().is_none() {
return Err(email_login_required("`offline setup`", &config));
}
ensure_provisioned(
&mut config,
ProvisionOptions {
app_name: &args.app_name,
org_name: args.org_name.as_deref(),
key_alias: Some(&args.key_alias),
product: &args.product,
},
)
.await?;
if args.json {
output::json(&json!({
"orgId": config.org_id,
"appId": config.app_id,
"email": config.email,
"hasApiKey": config.effective_api_key().is_some(),
}))?;
} else {
output::success("Offline Protocol account is ready for CLI use");
if let Some(org_id) = &config.org_id {
output::note(&format!("organization: {org_id}"));
}
if let Some(app_id) = &config.app_id {
output::note(&format!("application: {app_id}"));
}
output::note("Run `offline create` to scaffold an app, or `offline whoami --verify` to check credentials");
}
Ok(())
}
pub async fn setup_for_create(
config: &mut CliConfig,
app_name: &str,
mesh_enabled: bool,
pol_enabled: bool,
interactive: bool,
) -> Result<()> {
if config.has_api_credentials() {
return Ok(());
}
crate::commands::provision::ensure_logged_in_for_provision(config, interactive).await?;
let config_reloaded = CliConfig::load()?;
*config = config_reloaded;
ensure_provisioned(
config,
ProvisionOptions {
app_name,
org_name: None,
key_alias: Some("CLI default"),
product: crate::commands::provision::product_for_create(mesh_enabled, pol_enabled),
},
)
.await
}