From a7a5e2e0a3f627911029a8ddba86d0102a01b8a9 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 5 Oct 2025 01:59:37 -0600 Subject: [PATCH] feat: add environment selection to database commands - Introduced environmentId flag to all database commands (create, delete, deploy, stop) 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 database instances. - Updated type definitions to include Database for better type safety. --- src/commands/database/mariadb/create.ts | 37 +++++++++++- src/commands/database/mariadb/delete.ts | 73 +++++++++++++++++------- src/commands/database/mariadb/deploy.ts | 49 +++++++++++++--- src/commands/database/mariadb/stop.ts | 73 +++++++++++++++++------- src/commands/database/mongo/create.ts | 37 +++++++++++- src/commands/database/mongo/delete.ts | 49 +++++++++++++--- src/commands/database/mongo/deploy.ts | 49 +++++++++++++--- src/commands/database/mongo/stop.ts | 73 +++++++++++++++++------- src/commands/database/mysql/create.ts | 37 +++++++++++- src/commands/database/mysql/delete.ts | 49 +++++++++++++--- src/commands/database/mysql/deploy.ts | 69 +++++++++++++++++++--- src/commands/database/mysql/stop.ts | 69 +++++++++++++++++++--- src/commands/database/postgres/create.ts | 37 +++++++++++- src/commands/database/postgres/delete.ts | 49 +++++++++++++--- src/commands/database/postgres/deploy.ts | 49 +++++++++++++--- src/commands/database/postgres/stop.ts | 73 +++++++++++++++++------- src/commands/database/redis/create.ts | 36 +++++++++++- src/commands/database/redis/delete.ts | 49 +++++++++++++--- src/commands/database/redis/deploy.ts | 73 +++++++++++++++++------- src/commands/database/redis/stop.ts | 73 +++++++++++++++++------- src/utils/shared.ts | 20 +++++-- 21 files changed, 914 insertions(+), 209 deletions(-) diff --git a/src/commands/database/mariadb/create.ts b/src/commands/database/mariadb/create.ts index 7ea7101..d2c4811 100644 --- a/src/commands/database/mariadb/create.ts +++ b/src/commands/database/mariadb/create.ts @@ -3,7 +3,7 @@ import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProjects } from "../../../utils/shared.js"; +import { getProjects, type Database } from "../../../utils/shared.js"; import { slugify } from "../../../utils/slug.js"; import type { Answers } from "../../app/create.js"; @@ -18,6 +18,11 @@ export default class DatabaseMariadbCreate 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: "Database name", @@ -64,6 +69,7 @@ export default class DatabaseMariadbCreate extends Command { const { flags } = await this.parse(DatabaseMariadbCreate); let { projectId, + environmentId, name, databaseName, description, @@ -75,10 +81,13 @@ export default class DatabaseMariadbCreate extends Command { } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !name || !databaseName || !appName) { + if (!projectId || !environmentId || !name || !databaseName || !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([ { @@ -91,7 +100,30 @@ export default class DatabaseMariadbCreate 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 || !databaseName || !appName) { @@ -195,6 +227,7 @@ export default class DatabaseMariadbCreate extends Command { dockerImage, appName, projectId, + environmentId, }, }, { diff --git a/src/commands/database/mariadb/delete.ts b/src/commands/database/mariadb/delete.ts index fa2a12e..87c9ba6 100644 --- a/src/commands/database/mariadb/delete.ts +++ b/src/commands/database/mariadb/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 Database } from "../../../utils/shared.js"; import { readAuthConfig } from "../../../utils/utils.js"; export default class DatabaseMariadbDelete extends Command { @@ -18,6 +18,11 @@ export default class DatabaseMariadbDelete extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mariadbId: Flags.string({ char: "m", description: "ID of the MariaDB instance to delete", @@ -33,12 +38,16 @@ export default class DatabaseMariadbDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMariadbDelete); - let { projectId, mariadbId } = flags; + let { projectId, environmentId, mariadbId } = flags; - if (!projectId || !mariadbId) { + if (!projectId || !environmentId || !mariadbId) { 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 answers = await inquirer.prompt([ { @@ -51,30 +60,54 @@ export default class DatabaseMariadbDelete extends Command { type: "list", }, ]); + selectedProject = projects.find(p => p.projectId === answers.selectedProject); projectId = answers.selectedProject; + } 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.mariadb || projectSelected.mariadb.length === 0) { - this.error(chalk.yellow("No MariaDB instances 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 MariaDB del environment if (!mariadbId) { + if (!selectedEnvironment?.mariadb || selectedEnvironment.mariadb.length === 0) { + this.error(chalk.yellow("No MariaDB instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ - { - // @ts-ignore - choices: projectSelected.mariadb.map((db) => ({ - name: db.name, - value: db.mariadbId, - })), - message: "Select the MariaDB instance to delete:", - name: "selectedDb", - type: "list", - }, - ]); - mariadbId = dbAnswers.selectedDb; - } + { + choices: selectedEnvironment.mariadb.map((db: Database) => ({ + name: db.name, + value: db.mariadbId, + })), + message: "Select the MariaDB instance to delete:", + name: "selectedDb", + type: "list", + }, + ]); + mariadbId = dbAnswers.selectedDb; + } } if (!flags.skipConfirm) { diff --git a/src/commands/database/mariadb/deploy.ts b/src/commands/database/mariadb/deploy.ts index 0209e53..bc54751 100644 --- a/src/commands/database/mariadb/deploy.ts +++ b/src/commands/database/mariadb/deploy.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class DatabaseMariadbDeploy extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mariadbId: Flags.string({ char: "m", description: "ID of the MariaDB instance to deploy", @@ -32,13 +37,17 @@ export default class DatabaseMariadbDeploy extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMariadbDeploy); - let { projectId, mariadbId } = flags; + let { projectId, environmentId, mariadbId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mariadbId) { + if (!projectId || !environmentId || !mariadbId) { 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,20 +60,44 @@ export default class DatabaseMariadbDeploy 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.mariadb.length === 0) { - this.error(chalk.yellow("No MariaDB instances 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 MariaDB del environment if (!mariadbId) { + if (!selectedEnvironment?.mariadb || selectedEnvironment.mariadb.length === 0) { + this.error(chalk.yellow("No MariaDB instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.mariadb.map((db) => ({ + choices: selectedEnvironment.mariadb.map((db: Database) => ({ name: db.name, value: db.mariadbId, })), diff --git a/src/commands/database/mariadb/stop.ts b/src/commands/database/mariadb/stop.ts index cbc66ea..f5c9d7e 100644 --- a/src/commands/database/mariadb/stop.ts +++ b/src/commands/database/mariadb/stop.ts @@ -2,7 +2,7 @@ import { Command, Flags } from "@oclif/core"; import chalk from "chalk"; import inquirer from "inquirer"; import axios from "axios"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import { readAuthConfig } from "../../../utils/utils.js"; import type { Answers } from "../../app/create.js"; @@ -17,6 +17,11 @@ export default class DatabaseMariadbStop extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mariadbId: Flags.string({ char: "m", description: "ID of the MariaDB instance to stop", @@ -32,13 +37,17 @@ export default class DatabaseMariadbStop extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMariadbStop); - let { projectId, mariadbId } = flags; + let { projectId, environmentId, mariadbId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mariadbId) { + if (!projectId || !environmentId || !mariadbId) { 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,30 +60,54 @@ export default class DatabaseMariadbStop 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.mariadb.length === 0) { - this.error(chalk.yellow("No MariaDB instances 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 MariaDB del environment if (!mariadbId) { + if (!selectedEnvironment?.mariadb || selectedEnvironment.mariadb.length === 0) { + this.error(chalk.yellow("No MariaDB instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ - { - // @ts-ignore - choices: projectSelected.mariadb.map((db) => ({ - name: db.name, - value: db.mariadbId, - })), - message: "Select the MariaDB instance to stop:", - name: "selectedDb", - type: "list", - }, - ]); - mariadbId = dbAnswers.selectedDb; - } + { + choices: selectedEnvironment.mariadb.map((db: Database) => ({ + name: db.name, + value: db.mariadbId, + })), + message: "Select the MariaDB instance to stop:", + name: "selectedDb", + type: "list", + }, + ]); + mariadbId = dbAnswers.selectedDb; + } } // Confirmar si no se especifica --skipConfirm diff --git a/src/commands/database/mongo/create.ts b/src/commands/database/mongo/create.ts index 45ccc37..30ebd1b 100644 --- a/src/commands/database/mongo/create.ts +++ b/src/commands/database/mongo/create.ts @@ -3,7 +3,7 @@ import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProjects } from "../../../utils/shared.js"; +import { getProjects, type Database } from "../../../utils/shared.js"; import { slugify } from "../../../utils/slug.js"; import type { Answers } from "../../app/create.js"; @@ -18,6 +18,11 @@ export default class DatabaseMongoCreate 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: "Database name", @@ -60,6 +65,7 @@ export default class DatabaseMongoCreate extends Command { const { flags } = await this.parse(DatabaseMongoCreate); let { projectId, + environmentId, name, databaseName, description, @@ -70,10 +76,13 @@ export default class DatabaseMongoCreate extends Command { } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !name || !databaseName || !appName || !databasePassword) { + if (!projectId || !environmentId || !name || !databaseName || !appName || !databasePassword) { 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([ { @@ -86,9 +95,32 @@ export default class DatabaseMongoCreate 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 || !databaseName || !appName || !databasePassword) { const dbDetails = await inquirer.prompt([ { @@ -182,6 +214,7 @@ export default class DatabaseMongoCreate extends Command { dockerImage, appName, projectId, + environmentId, }, }, { diff --git a/src/commands/database/mongo/delete.ts b/src/commands/database/mongo/delete.ts index dbbff26..1fe34eb 100644 --- a/src/commands/database/mongo/delete.ts +++ b/src/commands/database/mongo/delete.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; export default class DatabaseMongoDelete extends Command { static description = "Delete a MongoDB database from a project."; @@ -20,6 +20,11 @@ export default class DatabaseMongoDelete extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mongoId: Flags.string({ char: "m", description: "ID of the MongoDB instance to delete", @@ -35,13 +40,17 @@ export default class DatabaseMongoDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMongoDelete); - let { projectId, mongoId } = flags; + let { projectId, environmentId, mongoId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mongoId) { + if (!projectId || !environmentId || !mongoId) { 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 answers = await inquirer.prompt([ { @@ -54,20 +63,44 @@ export default class DatabaseMongoDelete extends Command { type: "list", }, ]); + selectedProject = projects.find(p => p.projectId === answers.selectedProject); projectId = answers.selectedProject; + } 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.mongo || projectSelected.mongo.length === 0) { - this.error(chalk.yellow("No MongoDB instances 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 MongoDB del environment if (!mongoId) { + if (!selectedEnvironment?.mongo || selectedEnvironment.mongo.length === 0) { + this.error(chalk.yellow("No MongoDB instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.mongo.map((db) => ({ + choices: selectedEnvironment.mongo.map((db: Database) => ({ name: db.name, value: db.mongoId, })), diff --git a/src/commands/database/mongo/deploy.ts b/src/commands/database/mongo/deploy.ts index dd4d074..7353d7a 100644 --- a/src/commands/database/mongo/deploy.ts +++ b/src/commands/database/mongo/deploy.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class DatabaseMongoDeploy extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mongoId: Flags.string({ char: "m", description: "ID of the MongoDB instance to deploy", @@ -32,13 +37,17 @@ export default class DatabaseMongoDeploy extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMongoDeploy); - let { projectId, mongoId } = flags; + let { projectId, environmentId, mongoId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mongoId) { + if (!projectId || !environmentId || !mongoId) { 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,20 +60,44 @@ export default class DatabaseMongoDeploy 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.mongo.length === 0) { - this.error(chalk.yellow("No MongoDB instances 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 MongoDB del environment if (!mongoId) { + if (!selectedEnvironment?.mongo || selectedEnvironment.mongo.length === 0) { + this.error(chalk.yellow("No MongoDB instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.mongo.map((db) => ({ + choices: selectedEnvironment.mongo.map((db: Database) => ({ name: db.name, value: db.mongoId, })), diff --git a/src/commands/database/mongo/stop.ts b/src/commands/database/mongo/stop.ts index 0ead2aa..e26f9ce 100644 --- a/src/commands/database/mongo/stop.ts +++ b/src/commands/database/mongo/stop.ts @@ -2,7 +2,7 @@ import { Command, Flags } from "@oclif/core"; import chalk from "chalk"; import inquirer from "inquirer"; import axios from "axios"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import { readAuthConfig } from "../../../utils/utils.js"; import type { Answers } from "../../app/create.js"; @@ -17,6 +17,11 @@ export default class DatabaseMongoStop extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mongoId: Flags.string({ char: "m", description: "ID of the MongoDB instance to stop", @@ -32,13 +37,17 @@ export default class DatabaseMongoStop extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMongoStop); - let { projectId, mongoId } = flags; + let { projectId, environmentId, mongoId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mongoId) { + if (!projectId || !environmentId || !mongoId) { 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,30 +60,54 @@ export default class DatabaseMongoStop 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.mongo.length === 0) { - this.error(chalk.yellow("No MongoDB instances 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 MongoDB del environment if (!mongoId) { + if (!selectedEnvironment?.mongo || selectedEnvironment.mongo.length === 0) { + this.error(chalk.yellow("No MongoDB instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ - { - // @ts-ignore - choices: projectSelected.mongo.map((db) => ({ - name: db.name, - value: db.mongoId, - })), - message: "Select the MongoDB instance to stop:", - name: "selectedDb", - type: "list", - }, - ]); - mongoId = dbAnswers.selectedDb; - } + { + choices: selectedEnvironment.mongo.map((db: Database) => ({ + name: db.name, + value: db.mongoId, + })), + message: "Select the MongoDB instance to stop:", + name: "selectedDb", + type: "list", + }, + ]); + mongoId = dbAnswers.selectedDb; + } } // Confirmar si no se especifica --skipConfirm diff --git a/src/commands/database/mysql/create.ts b/src/commands/database/mysql/create.ts index 525758b..402e8cb 100644 --- a/src/commands/database/mysql/create.ts +++ b/src/commands/database/mysql/create.ts @@ -5,7 +5,7 @@ import inquirer from "inquirer"; import { slugify } from "../../../utils/slug.js"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProjects } from "../../../utils/shared.js"; +import { getProjects, type Database } from "../../../utils/shared.js"; import type { Answers } from "../../app/create.js"; export default class DatabaseMysqlCreate extends Command { @@ -19,6 +19,11 @@ export default class DatabaseMysqlCreate 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: "Database name", @@ -65,6 +70,7 @@ export default class DatabaseMysqlCreate extends Command { const { flags } = await this.parse(DatabaseMysqlCreate); let { projectId, + environmentId, name, databaseName, description, @@ -76,10 +82,13 @@ export default class DatabaseMysqlCreate extends Command { } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !name || !databaseName || !appName || !databasePassword || !databaseRootPassword) { + if (!projectId || !environmentId || !name || !databaseName || !appName || !databasePassword || !databaseRootPassword) { 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([ { @@ -92,7 +101,30 @@ export default class DatabaseMysqlCreate 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 || !databaseName || !appName || !databasePassword || !databaseRootPassword) { @@ -197,6 +229,7 @@ export default class DatabaseMysqlCreate extends Command { dockerImage, appName, projectId, + environmentId, }, }, { diff --git a/src/commands/database/mysql/delete.ts b/src/commands/database/mysql/delete.ts index b896afd..c05c442 100644 --- a/src/commands/database/mysql/delete.ts +++ b/src/commands/database/mysql/delete.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; export default class DatabaseMysqlDelete extends Command { static description = "Delete a MySQL database from a project."; @@ -20,6 +20,11 @@ export default class DatabaseMysqlDelete extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), mysqlId: Flags.string({ char: "i", description: "ID of the MySQL database", @@ -35,13 +40,17 @@ export default class DatabaseMysqlDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMysqlDelete); - let { projectId, mysqlId } = flags; + let { projectId, environmentId, mysqlId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mysqlId) { + if (!projectId || !environmentId || !mysqlId) { 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 answers = await inquirer.prompt([ { @@ -54,20 +63,44 @@ export default class DatabaseMysqlDelete extends Command { type: "list", }, ]); + selectedProject = projects.find(p => p.projectId === answers.selectedProject); projectId = answers.selectedProject; + } 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.mysql || projectSelected.mysql.length === 0) { - this.error(chalk.yellow("No MySQL instances 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 MySQL del environment if (!mysqlId) { + if (!selectedEnvironment?.mysql || selectedEnvironment.mysql.length === 0) { + this.error(chalk.yellow("No MySQL instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.mysql.map((db) => ({ + choices: selectedEnvironment.mysql.map((db: Database) => ({ name: db.name, value: db.mysqlId, })), diff --git a/src/commands/database/mysql/deploy.ts b/src/commands/database/mysql/deploy.ts index 6e63b4e..747027b 100644 --- a/src/commands/database/mysql/deploy.ts +++ b/src/commands/database/mysql/deploy.ts @@ -1,7 +1,7 @@ -import { Command } from "@oclif/core"; +import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -11,16 +11,43 @@ export default class DatabaseMysqlDeploy extends Command { static examples = ["$ <%= config.bin %> app deploy"]; + static flags = { + projectId: Flags.string({ + char: "p", + description: "ID of the project", + required: false, + }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), + mysqlId: Flags.string({ + char: "m", + description: "ID of the MySQL instance to deploy", + required: false, + }), + skipConfirm: Flags.boolean({ + char: "y", + description: "Skip confirmation prompt", + default: false, + }), + }; + public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMysqlDeploy); - let { projectId, mysqlId } = flags; + let { projectId, environmentId, mysqlId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mysqlId) { + if (!projectId || !environmentId || !mysqlId) { 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([ { @@ -33,20 +60,44 @@ export default class DatabaseMysqlDeploy 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.mysql.length === 0) { - this.error(chalk.yellow("No MySQL instances 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 MySQL del environment if (!mysqlId) { + if (!selectedEnvironment?.mysql || selectedEnvironment.mysql.length === 0) { + this.error(chalk.yellow("No MySQL instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.mysql.map((db) => ({ + choices: selectedEnvironment.mysql.map((db: Database) => ({ name: db.name, value: db.mysqlId, })), diff --git a/src/commands/database/mysql/stop.ts b/src/commands/database/mysql/stop.ts index 22173fa..50ca2f6 100644 --- a/src/commands/database/mysql/stop.ts +++ b/src/commands/database/mysql/stop.ts @@ -1,8 +1,8 @@ -import { Command } from "@oclif/core"; +import { Command, Flags } from "@oclif/core"; import chalk from "chalk"; import inquirer from "inquirer"; import axios from "axios"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import { readAuthConfig } from "../../../utils/utils.js"; import type { Answers } from "../../app/create.js"; @@ -11,16 +11,43 @@ export default class DatabaseMysqlStop extends Command { static examples = ["$ <%= config.bin %> mysql stop"]; + static flags = { + projectId: Flags.string({ + char: "p", + description: "ID of the project", + required: false, + }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), + mysqlId: Flags.string({ + char: "i", + description: "ID of the MySQL database", + required: false, + }), + skipConfirm: Flags.boolean({ + char: "y", + description: "Skip confirmation", + required: false, + }), + }; + public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseMysqlStop); - let { projectId, mysqlId } = flags; + let { projectId, environmentId, mysqlId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !mysqlId) { + if (!projectId || !environmentId || !mysqlId) { 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([ { @@ -33,20 +60,44 @@ export default class DatabaseMysqlStop 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.mysql.length === 0) { - this.error(chalk.yellow("No MySQL instances 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 MySQL del environment if (!mysqlId) { + if (!selectedEnvironment?.mysql || selectedEnvironment.mysql.length === 0) { + this.error(chalk.yellow("No MySQL instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.mysql.map((db) => ({ + choices: selectedEnvironment.mysql.map((db: Database) => ({ name: db.name, value: db.mysqlId, })), diff --git a/src/commands/database/postgres/create.ts b/src/commands/database/postgres/create.ts index f0e96ff..55db1b7 100644 --- a/src/commands/database/postgres/create.ts +++ b/src/commands/database/postgres/create.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { slugify } from "../../../utils/slug.js"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProjects } from "../../../utils/shared.js"; +import { getProjects, type Database } from "../../../utils/shared.js"; import type { Answers } from "../../app/create.js"; export default class DatabasePostgresCreate extends Command { static description = "Create a new PostgreSQL database within a project."; @@ -17,6 +17,11 @@ export default class DatabasePostgresCreate 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: "Database name", @@ -59,6 +64,7 @@ export default class DatabasePostgresCreate extends Command { const { flags } = await this.parse(DatabasePostgresCreate); let { projectId, + environmentId, name, databaseName, description, @@ -69,10 +75,13 @@ export default class DatabasePostgresCreate extends Command { } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !name || !databaseName || !appName || !databasePassword) { + if (!projectId || !environmentId || !name || !databaseName || !appName || !databasePassword) { 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([ { @@ -85,9 +94,32 @@ export default class DatabasePostgresCreate 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 || !databaseName || !appName || !databasePassword) { const dbDetails = await inquirer.prompt([ { @@ -182,6 +214,7 @@ export default class DatabasePostgresCreate extends Command { dockerImage, appName, projectId, + environmentId, }, }, { diff --git a/src/commands/database/postgres/delete.ts b/src/commands/database/postgres/delete.ts index e6d6771..339d66c 100644 --- a/src/commands/database/postgres/delete.ts +++ b/src/commands/database/postgres/delete.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; export default class DatabasePostgresDelete extends Command { static description = "Delete a PostgreSQL database from a project."; @@ -20,6 +20,11 @@ export default class DatabasePostgresDelete extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), postgresId: Flags.string({ char: "d", description: "ID of the PostgreSQL database", @@ -35,13 +40,17 @@ export default class DatabasePostgresDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabasePostgresDelete); - let { projectId, postgresId } = flags; + let { projectId, environmentId, postgresId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !postgresId) { + if (!projectId || !environmentId || !postgresId) { 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 answers = await inquirer.prompt([ { @@ -54,20 +63,44 @@ export default class DatabasePostgresDelete extends Command { type: "list", }, ]); + selectedProject = projects.find(p => p.projectId === answers.selectedProject); projectId = answers.selectedProject; + } 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.postgres || projectSelected.postgres.length === 0) { - this.error(chalk.yellow("No PostgreSQL instances 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 PostgreSQL del environment if (!postgresId) { + if (!selectedEnvironment?.postgres || selectedEnvironment.postgres.length === 0) { + this.error(chalk.yellow("No PostgreSQL instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.postgres.map((db) => ({ + choices: selectedEnvironment.postgres.map((db: Database) => ({ name: db.name, value: db.postgresId, })), diff --git a/src/commands/database/postgres/deploy.ts b/src/commands/database/postgres/deploy.ts index 747c040..490994d 100644 --- a/src/commands/database/postgres/deploy.ts +++ b/src/commands/database/postgres/deploy.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class DatabasePostgresDeploy extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), postgresId: Flags.string({ char: "d", description: "ID of the PostgreSQL instance to deploy", @@ -32,13 +37,17 @@ export default class DatabasePostgresDeploy extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabasePostgresDeploy); - let { projectId, postgresId } = flags; + let { projectId, environmentId, postgresId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !postgresId) { + if (!projectId || !environmentId || !postgresId) { 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,20 +60,44 @@ export default class DatabasePostgresDeploy 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.postgres.length === 0) { - this.error(chalk.yellow("No PostgreSQL instances 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 PostgreSQL del environment if (!postgresId) { + if (!selectedEnvironment?.postgres || selectedEnvironment.postgres.length === 0) { + this.error(chalk.yellow("No PostgreSQL instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.postgres.map((db) => ({ + choices: selectedEnvironment.postgres.map((db: Database) => ({ name: db.name, value: db.postgresId, })), diff --git a/src/commands/database/postgres/stop.ts b/src/commands/database/postgres/stop.ts index ce6aa56..920c56b 100644 --- a/src/commands/database/postgres/stop.ts +++ b/src/commands/database/postgres/stop.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class DatabasePostgresStop extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), postgresId: Flags.string({ char: "d", description: "ID of the PostgreSQL instance to stop", @@ -32,13 +37,17 @@ export default class DatabasePostgresStop extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabasePostgresStop); - let { projectId, postgresId } = flags; + let { projectId, environmentId, postgresId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !postgresId) { + if (!projectId || !environmentId || !postgresId) { 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,30 +60,54 @@ export default class DatabasePostgresStop 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.postgres.length === 0) { - this.error(chalk.yellow("No PostgreSQL instances 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 PostgreSQL del environment if (!postgresId) { + if (!selectedEnvironment?.postgres || selectedEnvironment.postgres.length === 0) { + this.error(chalk.yellow("No PostgreSQL instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ - { - // @ts-ignore - choices: projectSelected.postgres.map((db) => ({ - name: db.name, - value: db.postgresId, - })), - message: "Select the PostgreSQL instance to stop:", - name: "selectedDb", - type: "list", - }, - ]); - postgresId = dbAnswers.selectedDb; - } + { + choices: selectedEnvironment.postgres.map((db: Database) => ({ + name: db.name, + value: db.postgresId, + })), + message: "Select the PostgreSQL instance to stop:", + name: "selectedDb", + type: "list", + }, + ]); + postgresId = dbAnswers.selectedDb; + } } // Confirmar si no se especifica --skipConfirm diff --git a/src/commands/database/redis/create.ts b/src/commands/database/redis/create.ts index 10fe3d9..4376b10 100644 --- a/src/commands/database/redis/create.ts +++ b/src/commands/database/redis/create.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { slugify } from "../../../utils/slug.js"; import { readAuthConfig } from "../../../utils/utils.js"; -import { getProjects } from "../../../utils/shared.js"; +import { getProjects, type Database } from "../../../utils/shared.js"; import type { Answers } from "../../app/create.js"; export default class DatabaseRedisCreate extends Command { @@ -18,6 +18,11 @@ export default class DatabaseRedisCreate 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: "Instance name", @@ -60,10 +65,13 @@ export default class DatabaseRedisCreate extends Command { } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !name || !appName || !databasePassword) { + if (!projectId || !environmentId || !name || !appName || !databasePassword) { 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([ { @@ -76,7 +84,30 @@ export default class DatabaseRedisCreate 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 || !databasePassword) { @@ -155,6 +186,7 @@ export default class DatabaseRedisCreate extends Command { dockerImage, appName, projectId, + environmentId, }, }, { diff --git a/src/commands/database/redis/delete.ts b/src/commands/database/redis/delete.ts index f85ce51..c1bba51 100644 --- a/src/commands/database/redis/delete.ts +++ b/src/commands/database/redis/delete.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -20,6 +20,11 @@ export default class DatabaseRedisDelete extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), redisId: Flags.string({ char: "r", description: "ID of the Redis instance to delete", @@ -35,13 +40,17 @@ export default class DatabaseRedisDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseRedisDelete); - let { projectId, redisId } = flags; + let { projectId, environmentId, redisId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !redisId) { + if (!projectId || !environmentId || !redisId) { 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 answers = await inquirer.prompt([ { @@ -54,20 +63,44 @@ export default class DatabaseRedisDelete extends Command { type: "list", }, ]); + selectedProject = projects.find(p => p.projectId === answers.selectedProject); projectId = answers.selectedProject; + } 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.redis || projectSelected.redis.length === 0) { - this.error(chalk.yellow("No Redis instances 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 Redis del environment if (!redisId) { + if (!selectedEnvironment?.redis || selectedEnvironment.redis.length === 0) { + this.error(chalk.yellow("No Redis instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ { - // @ts-ignore - choices: projectSelected.redis.map((db) => ({ + choices: selectedEnvironment.redis.map((db: Database) => ({ name: db.name, value: db.redisId, })), diff --git a/src/commands/database/redis/deploy.ts b/src/commands/database/redis/deploy.ts index 822ba52..5cd7d7b 100644 --- a/src/commands/database/redis/deploy.ts +++ b/src/commands/database/redis/deploy.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class DatabaseRedisDeploy extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), redisId: Flags.string({ char: "r", description: "ID of the Redis instance to deploy", @@ -32,13 +37,17 @@ export default class DatabaseRedisDeploy extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseRedisDeploy); - let { projectId, redisId } = flags; + let { projectId, environmentId, redisId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !redisId) { + if (!projectId || !environmentId || !redisId) { 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,30 +60,54 @@ export default class DatabaseRedisDeploy 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.redis.length === 0) { - this.error(chalk.yellow("No Redis instances 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 Redis del environment if (!redisId) { + if (!selectedEnvironment?.redis || selectedEnvironment.redis.length === 0) { + this.error(chalk.yellow("No Redis instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ - { - // @ts-ignore - choices: projectSelected.redis.map((db) => ({ - name: db.name, - value: db.redisId, - })), - message: "Select the Redis instance to deploy:", - name: "selectedDb", - type: "list", - }, - ]); - redisId = dbAnswers.selectedDb; - } + { + choices: selectedEnvironment.redis.map((db: Database) => ({ + name: db.name, + value: db.redisId, + })), + message: "Select the Redis instance to deploy:", + name: "selectedDb", + type: "list", + }, + ]); + redisId = dbAnswers.selectedDb; + } } // Confirmar si no se especifica --skipConfirm diff --git a/src/commands/database/redis/stop.ts b/src/commands/database/redis/stop.ts index 3a9b058..a71a2b5 100644 --- a/src/commands/database/redis/stop.ts +++ b/src/commands/database/redis/stop.ts @@ -1,7 +1,7 @@ import { Command, Flags } from "@oclif/core"; import { readAuthConfig } from "../../../utils/utils.js"; import chalk from "chalk"; -import { getProject, getProjects } from "../../../utils/shared.js"; +import { getProject, getProjects, type Database } from "../../../utils/shared.js"; import inquirer from "inquirer"; import type { Answers } from "../../app/create.js"; import axios from "axios"; @@ -17,6 +17,11 @@ export default class DatabaseRedisStop extends Command { description: "ID of the project", required: false, }), + environmentId: Flags.string({ + char: "e", + description: "ID of the environment", + required: false, + }), redisId: Flags.string({ char: "r", description: "ID of the Redis instance to stop", @@ -32,13 +37,17 @@ export default class DatabaseRedisStop extends Command { public async run(): Promise { const auth = await readAuthConfig(this); const { flags } = await this.parse(DatabaseRedisStop); - let { projectId, redisId } = flags; + let { projectId, environmentId, redisId } = flags; // Modo interactivo si no se proporcionan los flags necesarios - if (!projectId || !redisId) { + if (!projectId || !environmentId || !redisId) { 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,30 +60,54 @@ export default class DatabaseRedisStop 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.redis.length === 0) { - this.error(chalk.yellow("No Redis instances 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 Redis del environment if (!redisId) { + if (!selectedEnvironment?.redis || selectedEnvironment.redis.length === 0) { + this.error(chalk.yellow("No Redis instances found in this environment.")); + } + const dbAnswers = await inquirer.prompt([ - { - // @ts-ignore - choices: projectSelected.redis.map((db) => ({ - name: db.name, - value: db.redisId, - })), - message: "Select the Redis instance to stop:", - name: "selectedDb", - type: "list", - }, - ]); - redisId = dbAnswers.selectedDb; - } + { + choices: selectedEnvironment.redis.map((db: Database) => ({ + name: db.name, + value: db.redisId, + })), + message: "Select the Redis instance to stop:", + name: "selectedDb", + type: "list", + }, + ]); + redisId = dbAnswers.selectedDb; + } } // Confirmar si no se especifica --skipConfirm diff --git a/src/utils/shared.ts b/src/utils/shared.ts index a93d79d..ad7e832 100644 --- a/src/utils/shared.ts +++ b/src/utils/shared.ts @@ -11,6 +11,16 @@ export type Application = { // Add other application properties as needed }; +export type Database = { + mariadbId?: string; + mongoId?: string; + mysqlId?: string; + postgresId?: string; + redisId?: string; + name: string; + // Add other database properties as needed +}; + export type Environment = { name: string; environmentId: string; @@ -19,11 +29,11 @@ export type Environment = { env: string; projectId: string; applications: Application[]; - mariadb: any[]; - mongo: any[]; - mysql: any[]; - postgres: any[]; - redis: any[]; + mariadb: Database[]; + mongo: Database[]; + mysql: Database[]; + postgres: Database[]; + redis: Database[]; compose: any[]; };