diff --git a/.eslintrc.json b/.eslintrc.json index 1dfcfc4..b315bce 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,3 @@ { - "extends": ["oclif", "oclif-typescript", "prettier"] + "extends": [ "prettier"] } diff --git a/config.json b/config.json index e5834e2..14d290a 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,4 @@ { - "token": "5qdderpq2ejrjlu90hrnbjohvgc8j1u1k7i00um4", + "token": "icsy0appti460sbh5be1sevami702rc8a57l2e8h", "url": "http://localhost:3000" } \ No newline at end of file diff --git a/src/commands/app/create.ts b/src/commands/app/create.ts index 339d859..a9be784 100644 --- a/src/commands/app/create.ts +++ b/src/commands/app/create.ts @@ -3,8 +3,14 @@ import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; +import { type Project, getProjects } from "../../utils/shared.js"; +import { slugify } from "../../utils/slug.js"; import { readAuthConfig } from "../../utils/utils.js"; +export interface Answers { + project: Project; +} + export default class AppCreate extends Command { static description = "Create a new application within a project."; @@ -26,110 +32,72 @@ export default class AppCreate extends Command { let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { + const projects = await getProjects(auth, this); + + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the application in:", + name: "project", + type: "list", + }, + ]); + + projectId = project.projectId; + + const appDetails = await inquirer.prompt([ + { + message: "Enter the application name:", + name: "name", + type: "input", + validate: (input) => (input ? true : "Application name is required"), + }, + { + message: "Enter the application description (optional):", + name: "appDescription", + type: "input", + }, + ]); + + const appName = await inquirer.prompt([ + { + default: `${slugify(project.name)}-${appDetails.name}`, + message: "Enter the App name: (optional):", + name: "appName", + type: "input", + validate: (input) => (input ? true : "App name is required"), + }, + ]); + + const response = await axios.post( + `${auth.url}/api/trpc/application.create`, + { + json: { + ...appDetails, + appName: appName.appName, + projectId: project.projectId, + }, + }, + { headers: { Authorization: `Bearer ${auth.token}`, "Content-Type": "application/json", }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to create the database in:", - name: "selectedProject", - type: "list", - }, - ]); + }, + ); - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (response.status !== 200) { + this.error(chalk.red("Error creating application")); } - } - const databases = ["postgres", "mysql", "redis", "mariadb", "mongo"]; - - const databaseSelect = await inquirer.prompt([ - { - choices: databases.map((database: any) => ({ - name: database, - value: database, - })), - message: "Select a database to create the application in:", - name: "selectedDatabase", - type: "list", - }, - ]); - - const urlSelected = `${auth.url}/api/trpc/${databaseSelect.selectedDatabase}.create`; - - // Solicitar detalles de la nueva aplicación - const appDetails = await inquirer.prompt([ - { - message: "Enter the database name:", - name: "appName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Enter the database description (optional):", - name: "appDescription", - type: "input", - }, - ]); - - const { appDescription, appName } = appDetails; - - // Crear la aplicación en el proyecto seleccionado - try { - // const response = await axios.post( - // `${auth.url}/api/trpc/application.create`, - // { - // json: { - // description: appDescription, - // name: appName, - // projectId, - // }, - // }, - // { - // headers: { - // Authorization: `Bearer ${auth.token}`, - // "Content-Type": "application/json", - // }, - // }, - // ); - // if (!response.data.result.data.json) { - // this.error(chalk.red("Error creating application")); - // } - // this.log( - // chalk.green( - // `Application '${appName}' created successfully in project ID '${projectId}'.`, - // ), - // ); - } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to create application: ${error.message}`)); + this.log( + chalk.green(`Application '${appDetails.name}' created successfully.`), + ); } } } diff --git a/src/commands/app/delete.ts b/src/commands/app/delete.ts index 6a12f98..b8ca78b 100644 --- a/src/commands/app/delete.ts +++ b/src/commands/app/delete.ts @@ -3,7 +3,9 @@ import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; +import { getProject, getProjects } from "../../utils/shared.js"; import { readAuthConfig } from "../../utils/utils.js"; +import type { Answers } from "./create.js"; export default class AppDelete extends Command { static description = "Delete an application from a project."; @@ -29,77 +31,33 @@ export default class AppDelete extends Command { let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to delete the application from:", - name: "selectedProject", - type: "list", - }, - ]); - - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); - } - } + const projects = await getProjects(auth, this); - // Obtener la lista de aplicaciones del proyecto seleccionado - try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the application in:", + name: "project", + type: "list", }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching applications")); - } + ]); - const apps = response.data.result.data.json; + projectId = project.projectId; + const projectSelected = await getProject(projectId, auth, this); - if (apps.applications.length === 0) { - this.log(chalk.yellow("No applications found in this project.")); - return; + if (projectSelected.applications.length === 0) { + this.error(chalk.yellow("No applications found in this project.")); } - // Permitir al usuario seleccionar una aplicación const appAnswers = await inquirer.prompt([ { - choices: apps.applications.map((app: any) => ({ + // @ts-ignore + choices: projectSelected.applications.map((app) => ({ name: app.name, value: app.applicationId, })), @@ -111,7 +69,7 @@ export default class AppDelete extends Command { const applicationId = appAnswers.selectedApp; - // Confirmar eliminación + // // Confirmar eliminación const confirmAnswers = await inquirer.prompt([ { default: false, @@ -122,11 +80,9 @@ export default class AppDelete extends Command { ]); if (!confirmAnswers.confirmDelete) { - this.log(chalk.yellow("Application deletion cancelled.")); - return; + this.error(chalk.yellow("Application deletion cancelled.")); } - // Eliminar la aplicación seleccionada const deleteResponse = await axios.post( `${auth.url}/api/trpc/application.delete`, { @@ -147,9 +103,6 @@ export default class AppDelete extends Command { } this.log(chalk.green("Application deleted successfully.")); - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to delete application: ${error.message}`)); } } } diff --git a/src/commands/database/create.ts b/src/commands/database/create.ts deleted file mode 100644 index b9559d4..0000000 --- a/src/commands/database/create.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Command, Flags } from "@oclif/core"; -import axios from "axios"; -import chalk from "chalk"; -import inquirer from "inquirer"; - -import { readAuthConfig } from "../../utils/utils.js"; - -export default class DatabaseCreate extends Command { - static description = "Create a new database within a project."; - - static examples = ["$ <%= config.bin %> app create"]; - - static flags = { - projectId: Flags.string({ - char: "p", - description: "ID of the project", - required: false, - }), - }; - - public async run(): Promise { - const auth = await readAuthConfig(this); - - const { flags } = await this.parse(DatabaseCreate); - - let { projectId } = flags; - - if (!projectId) { - // Obtener la lista de proyectos y permitir la selección - console.log(chalk.blue.bold("\n Listing all Projects \n")); - - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to create the application in:", - name: "selectedProject", - type: "list", - }, - ]); - - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); - } - } - - // Solicitar detalles de la nueva aplicación - const appDetails = await inquirer.prompt([ - { - message: "Enter the database name:", - name: "appName", - type: "input", - validate: (input) => (input ? true : "Application name is required"), - }, - { - message: "Enter the application description (optional):", - name: "appDescription", - type: "input", - }, - ]); - - const { appDescription, appName } = appDetails; - - // Crear la aplicación en el proyecto seleccionado - try { - const response = await axios.post( - `${auth.url}/api/trpc/database.create`, - { - json: { - description: appDescription, - name: appName, - projectId, - }, - }, - { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }, - ); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error creating application")); - } - - this.log( - chalk.green( - `Application '${appName}' created successfully in project ID '${projectId}'.`, - ), - ); - } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to create application: ${error.message}`)); - } - } -} diff --git a/src/commands/database/mariadb/create.ts b/src/commands/database/mariadb/create.ts index 38b3f2a..676405c 100644 --- a/src/commands/database/mariadb/create.ts +++ b/src/commands/database/mariadb/create.ts @@ -2,12 +2,13 @@ import { Command, Flags } from "@oclif/core"; import axios from "axios"; 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 { slugify } from "../../../utils/slug.js"; +import type { Answers } from "../../app/create.js"; export default class DatabaseMariadbCreate extends Command { - static description = "Create a new database within a project."; + static description = "Create a new MariaDB database within a project."; static examples = ["$ <%= config.bin %> mariadb create"]; @@ -24,121 +25,105 @@ export default class DatabaseMariadbCreate extends Command { const { flags } = await this.parse(DatabaseMariadbCreate); - const { projectId } = flags; + let { projectId } = flags; + if (!projectId) { console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { + const projects = await getProjects(auth, this); + + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the MariaDB database in:", + name: "project", + type: "list", + }, + ]); + + projectId = project.projectId; + + const dbDetails = await inquirer.prompt([ + { + message: "Enter the name:", + name: "name", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Database name:", + name: "databaseName", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Enter the database description (optional):", + name: "description", + type: "input", + }, + { + message: "Database Root Password (optional):", + name: "databaseRootPassword", + type: "password", + }, + { + message: "Database password (optional):", + name: "databasePassword", + type: "password", + }, + { + default: "mariadb:4", + message: "Docker Image (default: mariadb:4):", + name: "dockerImage", + type: "input", + }, + { + default: "mariadb", + message: "Database User: (default: mariadb):", + name: "databaseUser", + type: "input", + }, + ]); + + const appName = await inquirer.prompt([ + { + default: `${slugify(project.name)}-${dbDetails.name}`, + message: "Enter the App name:", + name: "appName", + type: "input", + validate: (input) => (input ? true : "App name is required"), + }, + ]); + + const response = await axios.post( + `${auth.url}/api/trpc/mariadb.create`, + { + json: { + ...dbDetails, + appName: appName.appName, + projectId: project.projectId, + }, + }, + { headers: { Authorization: `Bearer ${auth.token}`, "Content-Type": "application/json", }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; + }, + ); - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - const { project } = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project, - })), - message: "Select a project to create the database in:", - name: "project", - type: "list", - }, - ]); - - const appDetails = await inquirer.prompt([ - { - message: "Enter the name:", - name: "name", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Database name:", - name: "databaseName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Enter the database description (optional):", - name: "description", - type: "input", - }, - { - message: "Database Root Password (optional):", - name: "databaseRootPassword", - type: "input", - }, - { - message: "Database password (optional):", - name: "databasePassword", - type: "input", - }, - { - default: "mariadb:4", - message: "Docker Image (default: mariadb:4):", - name: "dockerImage", - type: "input", - }, - { - default: "mariadb", - message: "Database User: (default: mariadb):", - name: "databaseUser", - type: "input", - }, - ]); - - const appName = await inquirer.prompt([ - { - default: `${slugify(project.name)}-${appDetails.name}`, - message: "Enter the App name: (optional):", - name: "appName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - ]); - - const responseDatabase = await axios.post( - `${auth.url}/api/trpc/mariadb.create`, - { - json: { - ...appDetails, - appName: appName.appName, - projectId: project.projectId, - }, - }, - { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }, - ); - - if (!responseDatabase.data.result.data.json) { - this.error(chalk.red("Error creating database")); - } - - this.log( - chalk.green(`Database '${appDetails.name}' created successfully.`), - ); - } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (!response.data.result.data.json) { + this.error(chalk.red("Error creating MariaDB database")); } + + this.log( + chalk.green( + `MariaDB database '${dbDetails.name}' created successfully.`, + ), + ); } } } diff --git a/src/commands/database/mariadb/delete.ts b/src/commands/database/mariadb/delete.ts index c79ad81..bc8dd4c 100644 --- a/src/commands/database/mariadb/delete.ts +++ b/src/commands/database/mariadb/delete.ts @@ -3,16 +3,15 @@ import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; +import { getProject, getProjects } from "../../../utils/shared.js"; import { readAuthConfig } from "../../../utils/utils.js"; export default class DatabaseMariadbDelete extends Command { - static description = "Delete an application from a project."; - + static description = "Delete a MariaDB database from a project."; static examples = [ "$ <%= config.bin %> mariadb delete", "$ <%= config.bin %> mariadb delete -p ", ]; - static flags = { projectId: Flags.string({ char: "p", @@ -23,108 +22,68 @@ export default class DatabaseMariadbDelete extends Command { public async run(): Promise { const auth = await readAuthConfig(this); - const { flags } = await this.parse(DatabaseMariadbDelete); let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); + const projects = await getProjects(auth, this); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to delete the mariadb database from:", - name: "selectedProject", - type: "list", - }, - ]); - - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (projects.length === 0) { + this.log(chalk.yellow("No projects found.")); + return; } - } - try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), + const answers = await inquirer.prompt([ + { + type: "list", + name: "selectedProject", + message: "Select a project to delete the MariaDB database from:", + choices: projects.map((project: any) => ({ + name: project.name, + value: project.projectId, + })), }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching applications")); - } + ]); + projectId = answers.selectedProject; + } - const apps = response.data.result.data.json; + try { + const project = await getProject(projectId, auth, this); - if (apps.mariadb.length === 0) { - this.log(chalk.yellow("No applications found in this project.")); + if (!project.mariadb || project.mariadb.length === 0) { + this.log(chalk.yellow("No MariaDB databases found in this project.")); return; } - // Permitir al usuario seleccionar una aplicación const appAnswers = await inquirer.prompt([ { - choices: apps.mariadb.map((app: any) => ({ - name: app.name, - value: app.mariadbId, - })), - message: "Select the mariadb database to delete:", - name: "selectedApp", type: "list", + name: "selectedDb", + message: "Select the MariaDB database to delete:", + choices: project.mariadb.map((db: any) => ({ + name: db.name, + value: db.mariadbId, + })), }, ]); - const mariadbId = appAnswers.selectedApp; + const mariadbId = appAnswers.selectedDb; - // Confirmar eliminación const confirmAnswers = await inquirer.prompt([ { - default: false, - message: "Are you sure you want to delete this mysql database?", - name: "confirmDelete", type: "confirm", + name: "confirmDelete", + message: "Are you sure you want to delete this MariaDB database?", + default: false, }, ]); if (!confirmAnswers.confirmDelete) { - this.log(chalk.yellow("Application deletion cancelled.")); + this.log(chalk.yellow("Database deletion cancelled.")); return; } - // Eliminar la aplicación seleccionada const deleteResponse = await axios.post( `${auth.url}/api/trpc/mariadb.remove`, { @@ -141,13 +100,14 @@ export default class DatabaseMariadbDelete extends Command { ); if (!deleteResponse.data.result.data.json) { - this.error(chalk.red("Error deleting application")); + this.error(chalk.red("Error deleting mariadb database")); } - - this.log(chalk.green("Application deleted successfully.")); + this.log(chalk.green("MariaDB database deleted successfully.")); } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to delete application: ${error.message}`)); + this.error( + // @ts-ignore + chalk.red(`Failed to delete MariaDB database: ${error.message}`), + ); } } } diff --git a/src/commands/database/mongo/create.ts b/src/commands/database/mongo/create.ts index df1c007..ecb486a 100644 --- a/src/commands/database/mongo/create.ts +++ b/src/commands/database/mongo/create.ts @@ -2,12 +2,13 @@ import { Command, Flags } from "@oclif/core"; import axios from "axios"; 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 { slugify } from "../../../utils/slug.js"; +import type { Answers } from "../../app/create.js"; export default class DatabaseMongoCreate extends Command { - static description = "Create a new database within a project."; + static description = "Create a new MongoDB database within a project."; static examples = ["$ <%= config.bin %> mongo create"]; @@ -21,95 +22,83 @@ export default class DatabaseMongoCreate extends Command { public async run(): Promise { const auth = await readAuthConfig(this); + const { flags } = await this.parse(DatabaseMongoCreate); - const { projectId } = flags; + let { projectId } = flags; + if (!projectId) { console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; + const projects = await getProjects(auth, this); + + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the MongoDB database in:", + name: "project", + type: "list", + }, + ]); + + projectId = project.projectId; + + const dbDetails = await inquirer.prompt([ + { + message: "Enter the name:", + name: "name", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Database name:", + name: "databaseName", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Enter the database description (optional):", + name: "description", + type: "input", + }, + { + message: "Database password (optional):", + name: "databasePassword", + type: "password", + }, + { + default: "mongo:6", + message: "Docker Image (default: mongo:6):", + name: "dockerImage", + type: "input", + }, + { + default: "mongo", + message: "Database User: (default: mongo):", + name: "databaseUser", + type: "input", + }, + ]); + + const appName = await inquirer.prompt([ + { + default: `${slugify(project.name)}-${dbDetails.name}`, + message: "Enter the App name:", + name: "appName", + type: "input", + validate: (input) => (input ? true : "App name is required"), + }, + ]); - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - const { project } = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project, - })), - message: "Select a project to create the database in:", - name: "project", - type: "list", - }, - ]); - - const appDetails = await inquirer.prompt([ - { - message: "Enter the name:", - name: "name", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Database name:", - name: "databaseName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Enter the database description (optional):", - name: "description", - type: "input", - }, - { - message: "Database password (optional):", - name: "databasePassword", - type: "input", - }, - { - default: "mongo:6", - message: "Docker Image (default: mongo:6):", - name: "dockerImage", - type: "input", - }, - { - default: "mongo", - message: "Database User: (default: mongo):", - name: "databaseUser", - type: "input", - }, - ]); - - const appName = await inquirer.prompt([ - { - default: `${slugify(project.name)}-${appDetails.name}`, - message: "Enter the App name: (optional):", - name: "appName", - type: "input", - validate: (input) => (input ? true : "App name is required"), - }, - ]); - - const responseDatabase = await axios.post( + try { + const response = await axios.post( `${auth.url}/api/trpc/mongo.create`, { json: { - ...appDetails, + ...dbDetails, appName: appName.appName, projectId: project.projectId, }, @@ -122,16 +111,20 @@ export default class DatabaseMongoCreate extends Command { }, ); - if (!responseDatabase.data.result.data.json) { - this.error(chalk.red("Error creating database")); + if (!response.data.result.data.json) { + this.error(chalk.red("Error creating MongoDB database")); } this.log( - chalk.green(`Database '${appDetails.name}' created successfully.`), + chalk.green( + `MongoDB database '${dbDetails.name}' created successfully.`, + ), ); } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + this.error( + // @ts-ignore + chalk.red(`Failed to create MongoDB database: ${error.message}`), + ); } } } diff --git a/src/commands/database/mongo/delete.ts b/src/commands/database/mongo/delete.ts index 40c829f..6bdabbc 100644 --- a/src/commands/database/mongo/delete.ts +++ b/src/commands/database/mongo/delete.ts @@ -4,9 +4,10 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; +import { getProject, getProjects } from "../../../utils/shared.js"; export default class DatabaseMongoDelete extends Command { - static description = "Delete an application from a project."; + static description = "Delete a MongoDB database from a project."; static examples = [ "$ <%= config.bin %> mongo delete", @@ -28,80 +29,45 @@ export default class DatabaseMongoDelete extends Command { let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to delete the mongo database from:", - name: "selectedProject", - type: "list", - }, - ]); + const projects = await getProjects(auth, this); - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (projects.length === 0) { + this.log(chalk.yellow("No projects found.")); + return; } - } - try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), + const answers = await inquirer.prompt([ + { + choices: projects.map((project: any) => ({ + name: project.name, + value: project.projectId, + })), + message: "Select a project to delete the MongoDB database from:", + name: "selectedProject", + type: "list", }, - }); + ]); - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching applications")); - } + projectId = answers.selectedProject; + } - const apps = response.data.result.data.json; + try { + const project = await getProject(projectId, auth, this); - if (apps.mongo.length === 0) { - this.log(chalk.yellow("No applications found in this project.")); + if (!project.mongo || project.mongo.length === 0) { + this.log(chalk.yellow("No MongoDB databases found in this project.")); return; } - // Permitir al usuario seleccionar una aplicación const appAnswers = await inquirer.prompt([ { - choices: apps.mongo.map((app: any) => ({ - name: app.name, - value: app.mongoId, + choices: project.mongo.map((db: any) => ({ + name: db.name, + value: db.mongoId, })), - message: "Select the mongo database to delete:", + message: "Select the MongoDB database to delete:", name: "selectedApp", type: "list", }, @@ -109,22 +75,20 @@ export default class DatabaseMongoDelete extends Command { const mongoId = appAnswers.selectedApp; - // Confirmar eliminación const confirmAnswers = await inquirer.prompt([ { default: false, - message: "Are you sure you want to delete this mongo database?", + message: "Are you sure you want to delete this MongoDB database?", name: "confirmDelete", type: "confirm", }, ]); if (!confirmAnswers.confirmDelete) { - this.log(chalk.yellow("Application deletion cancelled.")); + this.log(chalk.yellow("Database deletion cancelled.")); return; } - // Eliminar la aplicación seleccionada const deleteResponse = await axios.post( `${auth.url}/api/trpc/mongo.remove`, { @@ -141,13 +105,15 @@ export default class DatabaseMongoDelete extends Command { ); if (!deleteResponse.data.result.data.json) { - this.error(chalk.red("Error deleting application")); + this.error(chalk.red("Error deleting MongoDB database")); } - this.log(chalk.green("Application deleted successfully.")); + this.log(chalk.green("MongoDB database deleted successfully.")); } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to delete application: ${error.message}`)); + this.error( + // @ts-ignore + chalk.red(`Failed to delete MongoDB database: ${error.message}`), + ); } } } diff --git a/src/commands/database/mysql/create.ts b/src/commands/database/mysql/create.ts index eb286b7..8f654c5 100644 --- a/src/commands/database/mysql/create.ts +++ b/src/commands/database/mysql/create.ts @@ -5,9 +5,11 @@ import inquirer from "inquirer"; import { slugify } from "../../../utils/slug.js"; import { readAuthConfig } from "../../../utils/utils.js"; +import { getProjects } from "../../../utils/shared.js"; +import type { Answers } from "../../app/create.js"; export default class DatabaseMysqlCreate extends Command { - static description = "Create a new database within a project."; + static description = "Create a new MySQL database within a project."; static examples = ["$ <%= config.bin %> mysql create"]; @@ -21,100 +23,88 @@ export default class DatabaseMysqlCreate extends Command { public async run(): Promise { const auth = await readAuthConfig(this); + const { flags } = await this.parse(DatabaseMysqlCreate); - const { projectId } = flags; + let { projectId } = flags; + if (!projectId) { console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - const { project } = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project, - })), - message: "Select a project to create the database in:", - name: "project", - type: "list", - }, - ]); - - const appDetails = await inquirer.prompt([ - { - message: "Enter the name:", - name: "name", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Database name:", - name: "databaseName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Enter the database description (optional):", - name: "description", - type: "input", - }, - { - message: "Database Root Password (optional):", - name: "databaseRootPassword", - type: "input", - }, - { - message: "Database password (optional):", - name: "databasePassword", - type: "input", - }, - { - default: "mysql:8", - message: "Docker Image (default: mysql:8):", - name: "dockerImage", - type: "input", - }, - { - default: "mysql", - message: "Database User: (default: mysql):", - name: "databaseUser", - type: "input", - }, - ]); - - const appName = await inquirer.prompt([ - { - default: `${slugify(project.name)}-${appDetails.name}`, - message: "Enter the App name: (optional):", - name: "appName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - ]); + const projects = await getProjects(auth, this); + + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the MySQL database in:", + name: "project", + type: "list", + }, + ]); + + projectId = project.projectId; + + const dbDetails = await inquirer.prompt([ + { + message: "Enter the name:", + name: "name", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Database name:", + name: "databaseName", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Enter the database description (optional):", + name: "description", + type: "input", + }, + { + message: "Database Root Password (optional):", + name: "databaseRootPassword", + type: "password", + }, + { + message: "Database password (optional):", + name: "databasePassword", + type: "password", + }, + { + default: "mysql:8", + message: "Docker Image (default: mysql:8):", + name: "dockerImage", + type: "input", + }, + { + default: "mysql", + message: "Database User: (default: mysql):", + name: "databaseUser", + type: "input", + }, + ]); + + const appName = await inquirer.prompt([ + { + default: `${slugify(project.name)}-${dbDetails.name}`, + message: "Enter the App name:", + name: "appName", + type: "input", + validate: (input) => (input ? true : "App name is required"), + }, + ]); - const responseDatabase = await axios.post( + try { + const response = await axios.post( `${auth.url}/api/trpc/mysql.create`, { json: { - ...appDetails, + ...dbDetails, appName: appName.appName, projectId: project.projectId, }, @@ -127,16 +117,20 @@ export default class DatabaseMysqlCreate extends Command { }, ); - if (!responseDatabase.data.result.data.json) { - this.error(chalk.red("Error creating database")); + if (!response.data.result.data.json) { + this.error(chalk.red("Error creating MySQL database")); } this.log( - chalk.green(`Database '${appDetails.name}' created successfully.`), + chalk.green( + `MySQL database '${dbDetails.name}' created successfully.`, + ), ); } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + this.error( + // @ts-ignore + chalk.red(`Failed to create MySQL database: ${error.message}`), + ); } } } diff --git a/src/commands/database/mysql/delete.ts b/src/commands/database/mysql/delete.ts index bb49888..8ea0c01 100644 --- a/src/commands/database/mysql/delete.ts +++ b/src/commands/database/mysql/delete.ts @@ -4,9 +4,10 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; +import { getProject, getProjects } from "../../../utils/shared.js"; export default class DatabaseMysqlDelete extends Command { - static description = "Delete an application from a project."; + static description = "Delete a MySQL database from a project."; static examples = [ "$ <%= config.bin %> mysql delete", @@ -28,80 +29,46 @@ export default class DatabaseMysqlDelete extends Command { let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to delete the mysql database from:", - name: "selectedProject", - type: "list", - }, - ]); + const projects = await getProjects(auth, this); - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (projects.length === 0) { + this.log(chalk.yellow("No projects found.")); + return; } - } - try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), + const answers = await inquirer.prompt([ + { + choices: projects.map((project: any) => ({ + name: project.name, + value: project.projectId, + })), + message: "Select a project to delete the MySQL database from:", + name: "selectedProject", + type: "list", }, - }); + ]); - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching applications")); - } + projectId = answers.selectedProject; + } - const apps = response.data.result.data.json; + try { + const project = await getProject(projectId, auth, this); - if (apps.mysql.length === 0) { - this.log(chalk.yellow("No applications found in this project.")); + if (!project.mysql || project.mysql.length === 0) { + this.log(chalk.yellow("No MySQL databases found in this project.")); return; } // Permitir al usuario seleccionar una aplicación const appAnswers = await inquirer.prompt([ { - choices: apps.mysql.map((app: any) => ({ + choices: project.mysql.map((app: any) => ({ name: app.name, value: app.mysqlId, })), - message: "Select the mysql database to delete:", + message: "Select the MySQL database to delete:", name: "selectedApp", type: "list", }, diff --git a/src/commands/database/postgres/create.ts b/src/commands/database/postgres/create.ts index 94451db..6b8514f 100644 --- a/src/commands/database/postgres/create.ts +++ b/src/commands/database/postgres/create.ts @@ -2,12 +2,12 @@ import { Command, Flags } from "@oclif/core"; import axios from "axios"; 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 type { Answers } from "../../app/create.js"; export default class DatabasePostgresCreate extends Command { - static description = "Create a new database within a project."; + static description = "Create a new PostgreSQL database within a project."; static examples = ["$ <%= config.bin %> postgres create"]; @@ -24,94 +24,80 @@ export default class DatabasePostgresCreate extends Command { const { flags } = await this.parse(DatabasePostgresCreate); - const { projectId } = flags; + let { projectId } = flags; + if (!projectId) { console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - const { project } = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project, - })), - message: "Select a project to create the database in:", - name: "project", - type: "list", - }, - ]); - - const appDetails = await inquirer.prompt([ - { - message: "Enter the name:", - name: "name", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Database name:", - name: "databaseName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Enter the database description (optional):", - name: "description", - type: "input", - }, - { - message: "Database password (optional):", - name: "databasePassword", - type: "input", - }, - { - default: "postgres:15", - message: "Docker Image (default: postgres:15):", - name: "dockerImage", - type: "input", - }, - - { - default: "postgres", - message: "Database User: (default: postgres):", - name: "databaseUser", - type: "input", - }, - ]); - - const appName = await inquirer.prompt([ - { - default: `${slugify(project.name)}-${appDetails.name}`, - message: "Enter the App name: (optional):", - name: "appName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - ]); + const projects = await getProjects(auth, this); + + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the PostgreSQL database in:", + name: "project", + type: "list", + }, + ]); + + projectId = project.projectId; + + const dbDetails = await inquirer.prompt([ + { + message: "Enter the name:", + name: "name", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Database name:", + name: "databaseName", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Enter the database description (optional):", + name: "description", + type: "input", + }, + { + message: "Database password (optional):", + name: "databasePassword", + type: "password", + }, + { + default: "postgres:15", + message: "Docker Image (default: postgres:15):", + name: "dockerImage", + type: "input", + }, + { + default: "postgres", + message: "Database User: (default: postgres):", + name: "databaseUser", + type: "input", + }, + ]); + + const appName = await inquirer.prompt([ + { + default: `${slugify(project.name)}-${dbDetails.name}`, + message: "Enter the App name:", + name: "appName", + type: "input", + validate: (input) => (input ? true : "App name is required"), + }, + ]); - const responseDatabase = await axios.post( + try { + const response = await axios.post( `${auth.url}/api/trpc/postgres.create`, { json: { - ...appDetails, + ...dbDetails, appName: appName.appName, projectId: project.projectId, }, @@ -124,16 +110,20 @@ export default class DatabasePostgresCreate extends Command { }, ); - if (!responseDatabase.data.result.data.json) { - this.error(chalk.red("Error creating database")); + if (!response.data.result.data.json) { + this.error(chalk.red("Error creating PostgreSQL database")); } this.log( - chalk.green(`Database '${appDetails.name}' created successfully.`), + chalk.green( + `PostgreSQL database '${dbDetails.name}' created successfully.`, + ), ); } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + this.error( + // @ts-ignore + chalk.red(`Failed to create PostgreSQL database: ${error.message}`), + ); } } } diff --git a/src/commands/database/postgres/delete.ts b/src/commands/database/postgres/delete.ts index 47aaf0e..e91298a 100644 --- a/src/commands/database/postgres/delete.ts +++ b/src/commands/database/postgres/delete.ts @@ -4,9 +4,10 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; +import { getProject, getProjects } from "../../../utils/shared.js"; export default class DatabasePostgresDelete extends Command { - static description = "Delete an application from a project."; + static description = "Delete a PostgreSQL database from a project."; static examples = [ "$ <%= config.bin %> postgres delete", @@ -28,80 +29,47 @@ export default class DatabasePostgresDelete extends Command { let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to delete the postgres database from:", - name: "selectedProject", - type: "list", - }, - ]); + const projects = await getProjects(auth, this); - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (projects.length === 0) { + this.log(chalk.yellow("No projects found.")); + return; } - } - try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), + const answers = await inquirer.prompt([ + { + choices: projects.map((project: any) => ({ + name: project.name, + value: project.projectId, + })), + message: "Select a project to delete the PostgreSQL database from:", + name: "selectedProject", + type: "list", }, - }); + ]); - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching applications")); - } + projectId = answers.selectedProject; + } - const apps = response.data.result.data.json; + try { + const project = await getProject(projectId, auth, this); - if (apps.postgres.length === 0) { - this.log(chalk.yellow("No applications found in this project.")); + if (!project.postgres || project.postgres.length === 0) { + this.log( + chalk.yellow("No PostgreSQL databases found in this project."), + ); return; } - // Permitir al usuario seleccionar una aplicación const appAnswers = await inquirer.prompt([ { - choices: apps.postgres.map((app: any) => ({ - name: app.name, - value: app.postgresId, + choices: project.postgres.map((db: any) => ({ + name: db.name, + value: db.postgresId, })), - message: "Select the postgres database to delete:", + message: "Select the PostgreSQL database to delete:", name: "selectedApp", type: "list", }, @@ -109,7 +77,6 @@ export default class DatabasePostgresDelete extends Command { const postgresId = appAnswers.selectedApp; - // Confirmar eliminación const confirmAnswers = await inquirer.prompt([ { default: false, @@ -120,11 +87,10 @@ export default class DatabasePostgresDelete extends Command { ]); if (!confirmAnswers.confirmDelete) { - this.log(chalk.yellow("Application deletion cancelled.")); + this.log(chalk.yellow("Database deletion cancelled.")); return; } - // Eliminar la aplicación seleccionada const deleteResponse = await axios.post( `${auth.url}/api/trpc/postgres.remove`, { @@ -141,10 +107,10 @@ export default class DatabasePostgresDelete extends Command { ); if (!deleteResponse.data.result.data.json) { - this.error(chalk.red("Error deleting application")); + this.error(chalk.red("Error deleting PostgreSQL database")); } - this.log(chalk.green("Application deleted successfully.")); + this.log(chalk.green("PostgreSQL database deleted successfully.")); } catch (error) { // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. this.error(chalk.red(`Failed to delete application: ${error.message}`)); diff --git a/src/commands/database/redis/create.ts b/src/commands/database/redis/create.ts index a68f00a..6a419e5 100644 --- a/src/commands/database/redis/create.ts +++ b/src/commands/database/redis/create.ts @@ -2,12 +2,13 @@ import { Command, Flags } from "@oclif/core"; import axios from "axios"; 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 type { Answers } from "../../app/create.js"; export default class DatabaseRedisCreate extends Command { - static description = "Create a new database within a project."; + static description = "Create a new Redis database within a project."; static examples = ["$ <%= config.bin %> redis create"]; @@ -21,82 +22,71 @@ export default class DatabaseRedisCreate extends Command { public async run(): Promise { const auth = await readAuthConfig(this); + const { flags } = await this.parse(DatabaseRedisCreate); - const { projectId } = flags; - if (!projectId) { - console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); + let { projectId } = flags; - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } + if (!projectId) { + console.log(chalk.blue.bold("\n Listing all Projects \n")); - const projects = response.data.result.data.json; + const projects = await getProjects(auth, this); - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } + const { project } = await inquirer.prompt([ + { + choices: projects.map((project) => ({ + name: project.name, + value: project, + })), + message: "Select a project to create the Redis database in:", + name: "project", + type: "list", + }, + ]); - const { project } = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project, - })), - message: "Select a project to create the database in:", - name: "project", - type: "list", - }, - ]); + projectId = project.projectId; - const appDetails = await inquirer.prompt([ - { - message: "Enter the name:", - name: "name", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - { - message: "Enter the database description (optional):", - name: "description", - type: "input", - }, - { - message: "Database password (optional):", - name: "databasePassword", - type: "input", - }, - { - default: "redis:7", - message: "Docker Image (default: redis:7):", - name: "dockerImage", - type: "input", - }, - ]); + const dbDetails = await inquirer.prompt([ + { + message: "Enter the name:", + name: "name", + type: "input", + validate: (input) => (input ? true : "Database name is required"), + }, + { + message: "Enter the database description (optional):", + name: "description", + type: "input", + }, + { + message: "Database password (optional):", + name: "databasePassword", + type: "password", + }, + { + default: "redis:7", + message: "Docker Image (default: redis:7):", + name: "dockerImage", + type: "input", + }, + ]); - const appName = await inquirer.prompt([ - { - default: `${slugify(project.name)}-${appDetails.name}`, - message: "Enter the App name: (optional):", - name: "appName", - type: "input", - validate: (input) => (input ? true : "Database name is required"), - }, - ]); + const appName = await inquirer.prompt([ + { + default: `${slugify(project.name)}-${dbDetails.name}`, + message: "Enter the App name:", + name: "appName", + type: "input", + validate: (input) => (input ? true : "App name is required"), + }, + ]); - const responseDatabase = await axios.post( + try { + const response = await axios.post( `${auth.url}/api/trpc/redis.create`, { json: { - ...appDetails, + ...dbDetails, appName: appName.appName, projectId: project.projectId, }, @@ -109,16 +99,20 @@ export default class DatabaseRedisCreate extends Command { }, ); - if (!responseDatabase.data.result.data.json) { - this.error(chalk.red("Error creating database")); + if (!response.data.result.data.json) { + this.error(chalk.red("Error creating Redis database")); } this.log( - chalk.green(`Database '${appDetails.name}' created successfully.`), + chalk.green( + `Redis database '${dbDetails.name}' created successfully.`, + ), ); } catch (error) { - // @ts-expect-error TODO: Fix this - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + this.error( + // @ts-ignore + chalk.red(`Failed to create Redis database: ${error.message}`), + ); } } } diff --git a/src/commands/database/redis/delete.ts b/src/commands/database/redis/delete.ts index 258927f..e47c5f1 100644 --- a/src/commands/database/redis/delete.ts +++ b/src/commands/database/redis/delete.ts @@ -4,9 +4,10 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../../utils/utils.js"; +import { getProject, getProjects } from "../../../utils/shared.js"; export default class DatabaseRedisDelete extends Command { - static description = "Delete an application from a project."; + static description = "Delete an redis database from a project."; static examples = [ "$ <%= config.bin %> redis delete", @@ -28,78 +29,44 @@ export default class DatabaseRedisDelete extends Command { let { projectId } = flags; if (!projectId) { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); - try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; - - if (projects.length === 0) { - this.log(chalk.yellow("No projects found.")); - return; - } - - // Permitir al usuario seleccionar un proyecto - const answers = await inquirer.prompt([ - { - choices: projects.map((project: any) => ({ - name: project.name, - value: project.projectId, - })), - message: "Select a project to delete the mariadb database from:", - name: "selectedProject", - type: "list", - }, - ]); + const projects = await getProjects(auth, this); - projectId = answers.selectedProject; - } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + if (projects.length === 0) { + this.log(chalk.yellow("No projects found.")); + return; } - } - try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), + const answers = await inquirer.prompt([ + { + choices: projects.map((project: any) => ({ + name: project.name, + value: project.projectId, + })), + message: "Select a project to delete the redis database from:", + name: "selectedProject", + type: "list", }, - }); + ]); - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching applications")); - } + projectId = answers.selectedProject; + } - const apps = response.data.result.data.json; + try { + const project = await getProject(projectId, auth, this); - if (apps.redis.length === 0) { - this.log(chalk.yellow("No applications found in this project.")); + if (!project.redis || project.redis.length === 0) { + this.log(chalk.yellow("No redis databases found in this project.")); return; } // Permitir al usuario seleccionar una aplicación const appAnswers = await inquirer.prompt([ { - choices: apps.redis.map((app: any) => ({ - name: app.name, - value: app.redisId, + choices: project.redis.map((db: any) => ({ + name: db.name, + value: db.redisId, })), message: "Select the redis database to delete:", name: "selectedApp", @@ -109,22 +76,20 @@ export default class DatabaseRedisDelete extends Command { const redisId = appAnswers.selectedApp; - // Confirmar eliminación const confirmAnswers = await inquirer.prompt([ { default: false, - message: "Are you sure you want to delete this mysql database?", + message: "Are you sure you want to delete this redis database?", name: "confirmDelete", type: "confirm", }, ]); if (!confirmAnswers.confirmDelete) { - this.log(chalk.yellow("Application deletion cancelled.")); + this.log(chalk.yellow("Database deletion cancelled.")); return; } - // Eliminar la aplicación seleccionada const deleteResponse = await axios.post( `${auth.url}/api/trpc/redis.remove`, { @@ -141,13 +106,15 @@ export default class DatabaseRedisDelete extends Command { ); if (!deleteResponse.data.result.data.json) { - this.error(chalk.red("Error deleting application")); + this.error(chalk.red("Error deleting redis database")); } - this.log(chalk.green("Application deleted successfully.")); + this.log(chalk.green("Redis database deleted successfully.")); } catch (error) { - // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. - this.error(chalk.red(`Failed to delete application: ${error.message}`)); + this.error( + // @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError'. + chalk.red(`Failed to delete redis database: ${error.message}`), + ); } } } diff --git a/src/commands/project/info.ts b/src/commands/project/info.ts index 44e3bdb..ded21ce 100644 --- a/src/commands/project/info.ts +++ b/src/commands/project/info.ts @@ -1,9 +1,9 @@ import { Command, Flags } from "@oclif/core"; -import axios from "axios"; import chalk from "chalk"; import inquirer from "inquirer"; import { readAuthConfig } from "../../utils/utils.js"; +import { getProject, getProjects } from "../../utils/shared.js"; export default class ProjectInfo extends Command { static description = @@ -28,35 +28,21 @@ export default class ProjectInfo extends Command { const { flags } = await this.parse(ProjectInfo); if (flags.projectId) { - // Si se proporciona un projectId, mostrar directamente la información del proyecto await this.showProjectInfo(auth, flags.projectId); } else { - // Obtener la lista de proyectos y permitir la selección console.log(chalk.blue.bold("\n Listing all Projects \n")); try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; + const projects = await getProjects(auth, this); if (projects.length === 0) { this.log(chalk.yellow("No projects found.")); return; } - // Permitir al usuario seleccionar un proyecto const answers = await inquirer.prompt([ { - choices: projects.map((project: any) => ({ + choices: projects.map((project) => ({ name: project.name, value: project.projectId, })), @@ -68,7 +54,7 @@ export default class ProjectInfo extends Command { const selectedProjectId = answers.selectedProject; - await this.showProjectInfo(auth, selectedProjectId); + await await this.showProjectInfo(auth, selectedProjectId); } catch (error) { // @ts-expect-error hola this.error(chalk.red(`Failed to fetch project list: ${error.message}`)); @@ -85,23 +71,7 @@ export default class ProjectInfo extends Command { ); try { - const response = await axios.get(`${auth.url}/api/trpc/project.one`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - params: { - input: JSON.stringify({ - json: { projectId }, - }), - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching project information")); - } - - const projectInfo = response.data.result.data.json; + const projectInfo = await getProject(projectId, auth, this); this.log(chalk.green(`Project Name: ${projectInfo.name}`)); this.log( @@ -141,55 +111,55 @@ export default class ProjectInfo extends Command { if (projectInfo.applications.length > 0) { this.log(chalk.blue("\nApplications:")); - projectInfo.applications.forEach((app: any, index: number) => { + projectInfo.applications.forEach((app, index: number) => { this.log(` ${index + 1}. ${app.name}`); }); } if (projectInfo.compose.length > 0) { this.log(chalk.blue("\nCompose Services:")); - projectInfo.compose.forEach((service: any, index: number) => { + projectInfo.compose.forEach((service, index: number) => { this.log(` ${index + 1}. ${service.name}`); }); } if (projectInfo.mariadb.length > 0) { this.log(chalk.blue("\nMariaDB Databases:")); - projectInfo.mariadb.forEach((db: any, index: number) => { + projectInfo.mariadb.forEach((db, index: number) => { this.log(` ${index + 1}. ${db.name}`); }); } if (projectInfo.mongo.length > 0) { this.log(chalk.blue("\nMongoDB Databases:")); - projectInfo.mongo.forEach((db: any, index: number) => { + projectInfo.mongo.forEach((db, index: number) => { this.log(` ${index + 1}. ${db.name}`); }); } if (projectInfo.mysql.length > 0) { this.log(chalk.blue("\nMySQL Databases:")); - projectInfo.mysql.forEach((db: any, index: number) => { + projectInfo.mysql.forEach((db, index: number) => { this.log(` ${index + 1}. ${db.name}`); }); } if (projectInfo.postgres.length > 0) { this.log(chalk.blue("\nPostgreSQL Databases:")); - projectInfo.postgres.forEach((db: any, index: number) => { + projectInfo.postgres.forEach((db, index: number) => { this.log(` ${index + 1}. ${db.name}`); }); } if (projectInfo.redis.length > 0) { this.log(chalk.blue("\nRedis Databases:")); - projectInfo.redis.forEach((db: any, index: number) => { + projectInfo.redis.forEach((db, index: number) => { this.log(` ${index + 1}. ${db.name}`); }); } } catch (error) { this.error( - // @ts-expect-error hola + // @ts-expect-error chalk.red(`Failed to fetch project information: ${error.message}`), ); } diff --git a/src/commands/project/list.ts b/src/commands/project/list.ts index fcf355e..91242b6 100644 --- a/src/commands/project/list.ts +++ b/src/commands/project/list.ts @@ -1,9 +1,9 @@ import { Command } from "@oclif/core"; -import axios from "axios"; import chalk from "chalk"; import Table from "cli-table3"; import { readAuthConfig } from "../../utils/utils.js"; +import { getProjects } from "../../utils/shared.js"; export default class ProjectList extends Command { static description = "List all projects."; @@ -16,18 +16,7 @@ export default class ProjectList extends Command { console.log(chalk.blue.bold("\n Listing all Projects \n")); try { - const response = await axios.get(`${auth.url}/api/trpc/project.all`, { - headers: { - Authorization: `Bearer ${auth.token}`, - "Content-Type": "application/json", - }, - }); - - if (!response.data.result.data.json) { - this.error(chalk.red("Error fetching projects")); - } - - const projects = response.data.result.data.json; + const projects = await getProjects(auth, this); if (projects.length === 0) { this.log(chalk.yellow("No projects found.")); @@ -52,9 +41,9 @@ export default class ProjectList extends Command { this.log(table.toString()); } - } catch { + } catch (error) { // @ts-expect-error error is not defined - this.error(chalk.red(`Failed to list projects: ${error.message}`)); + this.error(chalk.red(`Failed to list projects: ${error?.message}`)); } } } diff --git a/src/utils/shared.ts b/src/utils/shared.ts new file mode 100644 index 0000000..c1ff412 --- /dev/null +++ b/src/utils/shared.ts @@ -0,0 +1,81 @@ +import type { Command } from "@oclif/core"; + +import axios from "axios"; +import chalk from "chalk"; + +import type { AuthConfig } from "./utils.js"; + +export type Project = { + adminId: string; + name: string; + projectId?: string | undefined; + description?: string | undefined; +}; + +export const getProjects = async ( + auth: AuthConfig, + command: Command, +): Promise => { + try { + const response = await axios.get(`${auth.url}/api/trpc/project.all`, { + headers: { + Authorization: `Bearer ${auth.token}`, + "Content-Type": "application/json", + }, + }); + + if (!response.data.result.data.json) { + command.error(chalk.red("Error fetching projects")); + } + + const projects = response.data.result.data.json; + + if (projects.length === 0) { + command.log(chalk.yellow("No projects found.")); + return []; + } + + return projects; + } catch { + // @ts-expect-error TODO: Fix this + command.error(chalk.red(`Failed to fetch project list: ${error.message}`)); + } +}; + +export const getProject = async ( + projectId: string | undefined, + auth: AuthConfig, + command: Command, +) => { + try { + if (!projectId) { + command.error(chalk.red("Project ID is required")); + } + const response = await axios.get(`${auth.url}/api/trpc/project.one`, { + headers: { + Authorization: `Bearer ${auth.token}`, + "Content-Type": "application/json", + }, + params: { + input: JSON.stringify({ + json: { projectId }, + }), + }, + }); + + if (!response.data.result.data.json) { + command.error(chalk.red("Error fetching project")); + } + + const project = response.data.result.data.json; + + if (!project) { + command.error(chalk.red("Error fetching project")); + } + + return project; + } catch { + // @ts-expect-error TODO: Fix this + command.error(chalk.red(`Failed to fetch project: ${error.message}`)); + } +}; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 419678f..c5db541 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -9,9 +9,12 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const configPath = path.join(__dirname, "..", "..", "config.json"); -export const readAuthConfig = async ( - command: Command, -): Promise<{ token: string; url: string }> => { +export type AuthConfig = { + token: string; + url: string; +}; + +export const readAuthConfig = async (command: Command): Promise => { if (!fs.existsSync(configPath)) { command.error( chalk.red(