/** * Diagnostic subcommands for CLI — all go through SDK. * * @module */ import { chalk, getCliSdk, formatStatus } from "../actions.js"; import { resolveUuid } from "../coolify-state.js"; /** Diagnose an application. */ export async function diagnoseAppCommand(query?: string): Promise { const resolved = query || resolveUuid(undefined); if (!resolved) { console.error( chalk.red("Error: No app name/UUID provided and no .coolify.json found"), ); return; } console.log(chalk.cyan(`Diagnosing application: ${resolved}...\n`)); try { const { application, recentDeployments, envVarCount, recentLogs, issues } = await getCliSdk().diagnose.app(resolved); console.log(chalk.bold("Application:")); console.log(` ${chalk.gray("Name:")} ${application.name}`); console.log(` ${chalk.gray("UUID:")} ${application.uuid}`); console.log( ` ${chalk.gray("Status:")} ${formatStatus(application.status)}`, ); console.log(` ${chalk.gray("FQDN:")} ${application.fqdn || "none"}`); console.log(` ${chalk.gray("Env vars:")} ${envVarCount}`); if (recentDeployments.length > 0) { console.log(chalk.bold("\nRecent Deployments:")); for (const d of recentDeployments) { const status = d.status?.includes("failed") ? chalk.red(d.status) : chalk.green(d.status); const id = (d.deployment_uuid || d.uuid || "").slice(0, 12) || "-"; const date = d.created_at ? new Date(d.created_at).toLocaleString() : ""; console.log(` ${chalk.gray(id)} ${status} ${chalk.gray(date)}`); } } if (recentLogs.length > 0) { console.log(chalk.bold("\nRecent Logs (last 5):")); for (const line of recentLogs.slice(-5)) { console.log(` ${chalk.gray(line)}`); } } if (issues.length > 0) { console.log(chalk.bold.red(`\nIssues (${issues.length}):`)); for (const issue of issues) { console.log(` ${chalk.red("!")} ${issue}`); } } else { console.log(chalk.bold.green("\nNo issues detected")); } } catch (error) { console.error( chalk.red( `Error: ${error instanceof Error ? error.message : String(error)}`, ), ); } } /** Diagnose a server. */ export async function diagnoseServerCommand(query: string): Promise { console.log(chalk.cyan(`Diagnosing server: ${query}...\n`)); try { const { server, resources, domains, issues } = await getCliSdk().diagnose.server(query); console.log(chalk.bold("Server:")); console.log(` ${chalk.gray("Name:")} ${server.name}`); console.log(` ${chalk.gray("UUID:")} ${server.uuid}`); console.log(` ${chalk.gray("IP:")} ${server.ip || "-"}`); console.log( ` ${chalk.gray("Reachable:")} ${server.is_reachable ? chalk.green("Yes") : chalk.red("No")}`, ); console.log(` ${chalk.gray("Resources:")} ${resources.length}`); console.log(` ${chalk.gray("Domains:")} ${domains.length}`); if (issues.length > 0) { console.log(chalk.bold.red(`\nIssues (${issues.length}):`)); for (const issue of issues) { console.log(` ${chalk.red("!")} ${issue}`); } } else { console.log(chalk.bold.green("\nNo issues detected")); } } catch (error) { console.error( chalk.red( `Error: ${error instanceof Error ? error.message : String(error)}`, ), ); } } /** Scan all infrastructure for issues. */ export async function scanIssuesCommand(): Promise { console.log(chalk.cyan("Scanning infrastructure...\n")); try { const { totalServers, totalApps, totalDatabases, totalServices, issues } = await getCliSdk().diagnose.infrastructure(); console.log(chalk.bold("Infrastructure Summary:")); console.log(` ${chalk.gray("Servers:")} ${totalServers}`); console.log(` ${chalk.gray("Apps:")} ${totalApps}`); console.log(` ${chalk.gray("Databases:")} ${totalDatabases}`); console.log(` ${chalk.gray("Services:")} ${totalServices}`); if (issues.length > 0) { console.log(chalk.bold.red(`\nIssues (${issues.length}):`)); for (const issue of issues) { console.log( ` ${chalk.red("!")} [${issue.type}] ${issue.resource} (${issue.uuid}): ${issue.message}`, ); } } else { console.log( chalk.bold.green("\nNo issues detected across all infrastructure"), ); } } catch (error) { console.error( chalk.red( `Error: ${error instanceof Error ? error.message : String(error)}`, ), ); } }