From 68786fb7f1e90bc2520162b9928bf8f0fc9be6c6 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 5 Oct 2025 01:36:52 -0600 Subject: [PATCH] feat: add environment selection to app management commands - Introduced environmentId flag to AppCreate, AppDelete, and AppStop commands for specifying the environment. - Implemented interactive prompts for selecting project and environment if flags are not provided. - Enhanced error handling for cases with no available environments or applications. - Updated type definitions to include Application for better type safety. --- src/commands/app/create.ts | 36 ++++++++++++++++++++++++++-- src/commands/app/delete.ts | 49 +++++++++++++++++++++++++++++++------- src/commands/app/stop.ts | 48 +++++++++++++++++++++++++++++++------ 3 files changed, 116 insertions(+), 17 deletions(-) diff --git a/src/commands/app/create.ts b/src/commands/app/create.ts index 91734f8..40b77c7 100644 --- a/src/commands/app/create.ts +++ b/src/commands/app/create.ts @@ -22,6 +22,11 @@ export default class AppCreate extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), name: Flags.string({ char: "n", description: "Application name", @@ -46,13 +51,16 @@ export default class AppCreate extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(AppCreate); - let { projectId, name, description, appName } = flags; + let { projectId, environmentId, name, description, appName } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !name || !appName) { + if (!projectId || !environmentId || !name || !appName) { console.log(chalk.blue.bold("\n Listing all Projects \n")); const projects = await getProjects(auth, this); + let selectedProject; + + // 1. Seleccionar proyecto if (!projectId) { const { project } = await inquirer.prompt([ { @@ -65,7 +73,30 @@ export default class AppCreate extends Command { type: "list", }, ]); + selectedProject = project; projectId = project.projectId; + } else { + selectedProject = projects.find(p => p.projectId === projectId); + } + + // 2. Seleccionar environment del proyecto + if (!environmentId) { + if (!selectedProject?.environments || selectedProject.environments.length === 0) { + this.error(chalk.yellow("No environments found in this project.")); + } + + const { environment } = await inquirer.prompt([ + { + choices: selectedProject.environments.map((env) => ({ + name: `${env.name} (${env.description})`, + value: env, + })), + message: "Select an environment:", + name: "environment", + type: "list", + }, + ]); + environmentId = environment.environmentId; } if (!name || !appName) { @@ -128,6 +159,7 @@ export default class AppCreate extends Command { appDescription: description, appName, projectId, + environmentId, }, }, { diff --git a/src/commands/app/delete.ts b/src/commands/app/delete.ts index 1d07438..af2a87b 100644 --- a/src/commands/app/delete.ts +++ b/src/commands/app/delete.ts @@ -3,7 +3,7 @@ import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; -import { getProject, getProjects } from "../../utils/shared.js"; +import { getProject, getProjects, type Application } from "../../utils/shared.js"; import { readAuthConfig } from "../../utils/utils.js"; import type { Answers } from "./create.js"; @@ -21,6 +21,11 @@ export default class AppDelete extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), applicationId: Flags.string({ char: 'a', description: 'ID of the application to delete', @@ -36,13 +41,17 @@ export default class AppDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(AppDelete); - let { projectId, applicationId } = flags; + let { projectId, environmentId, applicationId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !applicationId) { + if (!projectId || !environmentId || !applicationId) { console.log(chalk.blue.bold("\n Listing all Projects \n")); const projects = await getProjects(auth, this); + let selectedProject; + let selectedEnvironment; + + // 1. Seleccionar proyecto if (!projectId) { const { project } = await inquirer.prompt([ { @@ -55,20 +64,44 @@ export default class AppDelete extends Command { type: "list", }, ]); + selectedProject = project; projectId = project.projectId; + } else { + selectedProject = projects.find(p => p.projectId === projectId); } - const projectSelected = await getProject(projectId, auth, this); + // 2. Seleccionar environment del proyecto + if (!environmentId) { + if (!selectedProject?.environments || selectedProject.environments.length === 0) { + this.error(chalk.yellow("No environments found in this project.")); + } - if (projectSelected.applications.length === 0) { - this.error(chalk.yellow("No applications found in this project.")); + const { environment } = await inquirer.prompt([ + { + choices: selectedProject.environments.map((env) => ({ + name: `${env.name} (${env.description})`, + value: env, + })), + message: "Select an environment:", + name: "environment", + type: "list", + }, + ]); + selectedEnvironment = environment; + environmentId = environment.environmentId; + } else { + selectedEnvironment = selectedProject?.environments?.find(e => e.environmentId === environmentId); } + // 3. Seleccionar application del environment if (!applicationId) { + if (!selectedEnvironment?.applications || selectedEnvironment.applications.length === 0) { + this.error(chalk.yellow("No applications found in this environment.")); + } + const appAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.applications.map((app) => ({ + choices: selectedEnvironment.applications.map((app: Application) => ({ name: app.name, value: app.applicationId, })), diff --git a/src/commands/app/stop.ts b/src/commands/app/stop.ts index 1efd3ae..b642e24 100644 --- a/src/commands/app/stop.ts +++ b/src/commands/app/stop.ts @@ -2,7 +2,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../utils/utils.js"; import chalk from "chalk"; import inquirer from "inquirer"; -import { getProject, getProjects } from "../../utils/shared.js"; +import { getProject, getProjects, type Application } from "../../utils/shared.js"; import type { Answers } from "./create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class AppStop extends Command { description: 'ID of the project', required: false, }), + environmentId: Flags.string({ + char: 'e', + description: 'ID of the environment', + required: false, + }), applicationId: Flags.string({ char: 'a', description: 'ID of the application to stop', @@ -32,13 +37,17 @@ export default class AppStop extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(AppStop); - let { projectId, applicationId } = flags; + let { projectId, environmentId, applicationId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !applicationId) { + if (!projectId || !environmentId || !applicationId) { console.log(chalk.blue.bold("\n Listing all Projects \n")); const projects = await getProjects(auth, this); + let selectedProject; + let selectedEnvironment; + + // 1. Seleccionar proyecto if (!projectId) { const { project } = await inquirer.prompt([ { @@ -51,19 +60,44 @@ export default class AppStop extends Command { type: "list", }, ]); + selectedProject = project; projectId = project.projectId; + } else { + selectedProject = projects.find(p => p.projectId === projectId); } - const projectSelected = await getProject(projectId, auth, this); + // 2. Seleccionar environment del proyecto + if (!environmentId) { + if (!selectedProject?.environments || selectedProject.environments.length === 0) { + this.error(chalk.yellow("No environments found in this project.")); + } - if (projectSelected.applications.length === 0) { - this.error(chalk.yellow("No applications found in this project.")); + const { environment } = await inquirer.prompt([ + { + choices: selectedProject.environments.map((env) => ({ + name: `${env.name} (${env.description})`, + value: env, + })), + message: "Select an environment:", + name: "environment", + type: "list", + }, + ]); + selectedEnvironment = environment; + environmentId = environment.environmentId; + } else { + selectedEnvironment = selectedProject?.environments?.find(e => e.environmentId === environmentId); } + // 3. Seleccionar application del environment if (!applicationId) { + if (!selectedEnvironment?.applications || selectedEnvironment.applications.length === 0) { + this.error(chalk.yellow("No applications found in this environment.")); + } + const appAnswers = await inquirer.prompt([ { - choices: projectSelected.applications.map((app: { name: string; applicationId: string }) => ({ + choices: selectedEnvironment.applications.map((app: Application) => ({ name: app.name, value: app.applicationId, })),