feat: enhance CLI commands with improved flags and error handling

This commit introduces several improvements across multiple CLI commands:
- Added new flags for more flexible command usage
- Implemented interactive mode for commands when flags are not provided
- Improved error handling and messaging
- Added support for environment variable authentication
- Standardized confirmation prompts and error messages
- Enhanced type safety with TypeScript improvements
This commit is contained in:
Mauricio Siu
2025-02-23 21:29:45 -06:00
parent 7cb5369f15
commit 10cfe23763
26 changed files with 2483 additions and 1621 deletions

View File

@@ -22,65 +22,112 @@ export default class AppCreate extends Command {
description: "ID of the project",
required: false,
}),
name: Flags.string({
char: "n",
description: "Application name",
required: false,
}),
description: Flags.string({
char: "d",
description: "Application description",
required: false,
}),
appName: Flags.string({
description: "Docker app name",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(AppCreate);
let { projectId, name, description, appName } = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !name || !appName) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
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;
}
if (!name || !appName) {
const appDetails = await inquirer.prompt([
{
message: "Enter the application name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Application name is required"),
default: name,
},
{
message: "Enter the application description (optional):",
name: "appDescription",
type: "input",
default: description,
},
]);
name = appDetails.name;
description = appDetails.appDescription;
const appNamePrompt = await inquirer.prompt([
{
default: appName || `${slugify(name)}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
appName = appNamePrompt.appName;
}
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = 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",
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this application?',
default: false,
},
]);
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"),
},
]);
if (!confirm.proceed) {
this.error(chalk.yellow("Application creation cancelled."));
return;
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/application.create`,
{
json: {
...appDetails,
appName: appName.appName,
projectId: project.projectId,
name,
appDescription: description,
appName,
projectId,
},
},
{
@@ -95,9 +142,9 @@ export default class AppCreate extends Command {
this.error(chalk.red("Error creating application"));
}
this.log(
chalk.green(`Application '${appDetails.name}' created successfully.`),
);
this.log(chalk.green(`Application '${name}' created successfully.`));
} catch (error: any) {
this.error(chalk.red(`Error creating application: ${error.message}`));
}
}
}

View File

@@ -21,55 +21,68 @@ export default class AppDelete extends Command {
description: "ID of the project",
required: false,
}),
applicationId: Flags.string({
char: 'a',
description: 'ID of the application to delete',
required: false,
}),
skipConfirm: Flags.boolean({
char: 'y',
description: 'Skip confirmation prompt',
default: false,
})
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(AppDelete);
let { projectId, applicationId } = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !applicationId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the application in:",
name: "project",
type: "list",
},
]);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to delete the application from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
projectId = project.projectId;
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.applications.length === 0) {
this.error(chalk.yellow("No applications found in this project."));
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.applications.map((app) => ({
name: app.name,
value: app.applicationId,
})),
message: "Select the application to delete:",
name: "selectedApp",
type: "list",
},
]);
if (!applicationId) {
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.applications.map((app) => ({
name: app.name,
value: app.applicationId,
})),
message: "Select the application to delete:",
name: "selectedApp",
type: "list",
},
]);
applicationId = appAnswers.selectedApp;
}
}
const applicationId = appAnswers.selectedApp;
// // Confirmar eliminación
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
@@ -82,7 +95,9 @@ export default class AppDelete extends Command {
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("Application deletion cancelled."));
}
}
try {
const deleteResponse = await axios.post(
`${auth.url}/api/trpc/application.delete`,
{
@@ -103,6 +118,8 @@ export default class AppDelete extends Command {
}
this.log(chalk.green("Application deleted successfully."));
} catch (error: any) {
this.error(chalk.red(`Failed to delete application: ${error.message}`));
}
}
}

View File

@@ -1,4 +1,4 @@
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";
@@ -9,81 +9,116 @@ import axios from "axios";
export default class AppDeploy extends Command {
static description = "Deploy an application to a project.";
static examples = ["$ <%= config.bin %> app deploy"];
static examples = [
"$ <%= config.bin %> app deploy",
"$ <%= config.bin %> app deploy --applicationId myAppId",
"$ DOKPLOY_URL=xxx DOKPLOY_AUTH_TOKEN=xxx <%= config.bin %> app deploy --applicationId myAppId"
];
static flags = {
applicationId: Flags.string({
char: 'a',
description: 'ID of the application to deploy',
required: false,
}),
projectId: Flags.string({
char: 'p',
description: 'ID of the project',
required: false,
}),
skipConfirm: Flags.boolean({
char: 'y',
description: 'Skip confirmation prompt',
default: false,
})
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(AppDeploy);
let { projectId, applicationId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !applicationId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the application from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the application in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.applications.length === 0) {
this.error(chalk.yellow("No applications found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.applications.length === 0) {
this.error(chalk.yellow("No applications found in this project."));
if (!applicationId) {
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.applications.map((app) => ({
name: app.name,
value: app.applicationId,
})),
message: "Select the application to deploy:",
name: "selectedApp",
type: "list",
},
]);
applicationId = appAnswers.selectedApp;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.applications.map((app) => ({
name: app.name,
value: app.applicationId,
})),
message: "Select the application to deploy:",
name: "selectedApp",
type: "list",
},
]);
const applicationId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this application?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("Application deployment cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/application.deploy`,
{
json: {
applicationId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this application?",
name: "confirmDelete",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error deploying application"));
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("Application deployment cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/application.deploy`,
{
json: {
applicationId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error deploying application"));
}
this.log(chalk.green("Application deploy successful."));
} catch (error: any) {
this.error(chalk.red(`Error deploying application: ${error.message}`));
}
this.log(chalk.green("Application deploy successful."));
}
}

View File

@@ -1,4 +1,4 @@
import { Command } from "@oclif/core";
import { Command, Flags } from "@oclif/core";
import { readAuthConfig } from "../../utils/utils.js";
import chalk from "chalk";
import inquirer from "inquirer";
@@ -11,79 +11,109 @@ export default class AppStop extends Command {
static examples = ["$ <%= config.bin %> app stop"];
static flags = {
projectId: Flags.string({
char: 'p',
description: 'ID of the project',
required: false,
}),
applicationId: Flags.string({
char: 'a',
description: 'ID of the application to stop',
required: false,
}),
skipConfirm: Flags.boolean({
char: 'y',
description: 'Skip confirmation prompt',
default: false,
})
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(AppStop);
let { projectId, applicationId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !applicationId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the application from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the application in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.applications.length === 0) {
this.error(chalk.yellow("No applications found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.applications.length === 0) {
this.error(chalk.yellow("No applications found in this project."));
if (!applicationId) {
const appAnswers = await inquirer.prompt([
{
choices: projectSelected.applications.map((app: { name: string; applicationId: string }) => ({
name: app.name,
value: app.applicationId,
})),
message: "Select the application to stop:",
name: "selectedApp",
type: "list",
},
]);
applicationId = appAnswers.selectedApp;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.applications.map((app) => ({
name: app.name,
value: app.applicationId,
})),
message: "Select the application to stop:",
name: "selectedApp",
type: "list",
},
]);
const applicationId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this application?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("Application stop cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/application.stop`,
{
json: {
applicationId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this application?",
name: "confirmDelete",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error stopping application"));
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("Application stop cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/application.stop`,
{
json: {
applicationId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error stopping application"));
}
this.log(chalk.green("Application stop successful."));
} catch (error: any) {
this.error(chalk.red(`Error stopping application: ${error.message}`));
}
this.log(chalk.green("Application stop successful."));
}
}

View File

@@ -18,93 +18,194 @@ export default class DatabaseMariadbCreate extends Command {
description: "ID of the project",
required: false,
}),
name: Flags.string({
char: "n",
description: "Database name",
required: false,
}),
databaseName: Flags.string({
description: "MariaDB database name",
required: false,
}),
description: Flags.string({
char: "d",
description: "Database description",
required: false,
}),
databaseRootPassword: Flags.string({
description: "Database root password",
required: false,
}),
databasePassword: Flags.string({
description: "Database password",
required: false,
}),
databaseUser: Flags.string({
description: "Database user",
default: "mariadb",
}),
dockerImage: Flags.string({
description: "Docker image",
default: "mariadb:11",
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
appName: Flags.string({
description: "App name",
required: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMariadbCreate);
let {
projectId,
name,
databaseName,
description,
databaseRootPassword,
databasePassword,
databaseUser,
dockerImage,
appName
} = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !name || !databaseName || !appName) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the MariaDB instance in:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
if (!name || !databaseName || !appName) {
const dbDetails = await inquirer.prompt([
{
message: "Enter the name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: name,
},
{
message: "Database name:",
name: "databaseName",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: databaseName,
},
{
message: "Enter the database description (optional):",
name: "description",
type: "input",
default: description,
},
{
message: "Database Root Password (optional):",
name: "databaseRootPassword",
type: "password",
default: databaseRootPassword,
},
{
message: "Database password (optional):",
name: "databasePassword",
type: "password",
default: databasePassword,
},
{
default: dockerImage || "mariadb:11",
message: "Docker Image (default: mariadb:11):",
name: "dockerImage",
type: "input",
},
{
default: databaseUser || "mariadb",
message: "Database User: (default: mariadb):",
name: "databaseUser",
type: "input",
},
]);
name = dbDetails.name;
databaseName = dbDetails.databaseName;
description = dbDetails.description;
databaseRootPassword = dbDetails.databaseRootPassword;
databasePassword = dbDetails.databasePassword;
dockerImage = dbDetails.dockerImage;
databaseUser = dbDetails.databaseUser;
const appNamePrompt = await inquirer.prompt([
{
default: appName || `${slugify(name)}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
appName = appNamePrompt.appName;
}
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = 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",
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this MariaDB instance?',
default: false,
},
]);
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:11",
message: "Docker Image (default: mariadb:11):",
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"),
},
]);
if (!confirm.proceed) {
this.error(chalk.yellow("MariaDB creation cancelled."));
return;
}
}
try {
console.log(JSON.stringify({
name,
databaseName,
description,
databaseRootPassword,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
}, null, 2));
const response = await axios.post(
`${auth.url}/api/trpc/mariadb.create`,
{
json: {
...dbDetails,
appName: appName.appName,
projectId: project.projectId,
name,
databaseName,
description,
databaseRootPassword,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
},
},
{
@@ -116,14 +217,12 @@ export default class DatabaseMariadbCreate extends Command {
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating MariaDB database"));
this.error(chalk.red("Error creating MariaDB instance", response.data.result.data.json));
}
this.log(
chalk.green(
`MariaDB database '${dbDetails.name}' created successfully.`,
),
);
this.log(chalk.green(`MariaDB instance '${name}' created successfully.`));
} catch (error: any) {
this.error(chalk.red(`Error creating MariaDB instance: ${error.message}`));
}
}
}

View File

@@ -18,73 +18,82 @@ export default class DatabaseMariadbDelete extends Command {
description: "ID of the project",
required: false,
}),
mariadbId: Flags.string({
char: "m",
description: "ID of the MariaDB instance to delete",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMariadbDelete);
let { projectId } = flags;
let { projectId, mariadbId } = flags;
if (!projectId) {
if (!projectId || !mariadbId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
if (projects.length === 0) {
this.log(chalk.yellow("No projects found."));
return;
if (!projectId) {
const answers = await inquirer.prompt([
{
choices: projects.map((project) => ({
name: project.name,
value: project.projectId,
})),
message: "Select a project to delete the MariaDB instance from:",
name: "selectedProject",
type: "list",
},
]);
projectId = answers.selectedProject;
}
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,
})),
},
]);
projectId = answers.selectedProject;
const projectSelected = await getProject(projectId, auth, this);
if (!projectSelected.mariadb || projectSelected.mariadb.length === 0) {
this.error(chalk.yellow("No MariaDB instances found in this project."));
}
if (!mariadbId) {
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;
}
}
try {
const project = await getProject(projectId, auth, this);
if (!project.mariadb || project.mariadb.length === 0) {
this.log(chalk.yellow("No MariaDB databases found in this project."));
return;
}
const appAnswers = await inquirer.prompt([
{
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.selectedDb;
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
type: "confirm",
name: "confirmDelete",
message: "Are you sure you want to delete this MariaDB database?",
default: false,
message: "Are you sure you want to delete this MariaDB instance?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.log(chalk.yellow("Database deletion cancelled."));
return;
this.error(chalk.yellow("MariaDB deletion cancelled."));
}
}
const deleteResponse = await axios.post(
try {
const response = await axios.post(
`${auth.url}/api/trpc/mariadb.remove`,
{
json: {
@@ -99,15 +108,12 @@ export default class DatabaseMariadbDelete extends Command {
},
);
if (!deleteResponse.data.result.data.json) {
this.error(chalk.red("Error deleting mariadb database"));
if (!response.data.result.data.json) {
this.error(chalk.red("Error deleting MariaDB instance"));
}
this.log(chalk.green("MariaDB database deleted successfully."));
} catch (error) {
this.error(
// @ts-ignore
chalk.red(`Failed to delete MariaDB database: ${error.message}`),
);
this.log(chalk.green("MariaDB instance deleted successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deleting MariaDB instance: ${error.message}`));
}
}
}

View File

@@ -1,4 +1,4 @@
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";
@@ -11,79 +11,110 @@ export default class DatabaseMariadbDeploy extends Command {
static examples = ["$ <%= config.bin %> app deploy"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
mariadbId: Flags.string({
char: "m",
description: "ID of the MariaDB instance to deploy",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMariadbDeploy);
let { projectId, mariadbId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mariadbId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the MariaDB in:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the mariadb in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.mariadb.length === 0) {
this.error(chalk.yellow("No MariaDB instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.mariadb.length === 0) {
this.error(chalk.yellow("No mariadb found in this project."));
if (!mariadbId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mariadb.map((db) => ({
name: db.name,
value: db.mariadbId,
})),
message: "Select the MariaDB instance to deploy:",
name: "selectedDb",
type: "list",
},
]);
mariadbId = dbAnswers.selectedDb;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mariadb.map((app) => ({
name: app.name,
value: app.mariadbId,
})),
message: "Select the mariadb to deploy:",
name: "selectedApp",
type: "list",
},
]);
const mariadbId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this mariadb?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("mariadb deployment cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/mariadb.deploy`,
{
json: {
mariadbId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this MariaDB instance?",
name: "confirmDeploy",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error deploying mariadb"));
if (!confirmAnswers.confirmDeploy) {
this.error(chalk.yellow("MariaDB deployment cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mariadb.deploy`,
{
json: {
mariadbId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error deploying MariaDB instance"));
}
this.log(chalk.green("MariaDB instance deployed successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deploying MariaDB instance: ${error.message}`));
}
this.log(chalk.green("Mariadb deploy successful."));
}
}

View File

@@ -1,4 +1,4 @@
import { Command } from "@oclif/core";
import { Command, Flags } from "@oclif/core";
import chalk from "chalk";
import inquirer from "inquirer";
import axios from "axios";
@@ -11,79 +11,110 @@ export default class DatabaseMariadbStop extends Command {
static examples = ["$ <%= config.bin %> mariadb stop"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
mariadbId: Flags.string({
char: "m",
description: "ID of the MariaDB instance to stop",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMariadbStop);
let { projectId, mariadbId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mariadbId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the MariaDB instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the mariadb in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.mariadb.length === 0) {
this.error(chalk.yellow("No MariaDB instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.mariadb.length === 0) {
this.error(chalk.yellow("No mariadb found in this project."));
if (!mariadbId) {
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;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mariadb.map((app) => ({
name: app.name,
value: app.mariadbId,
})),
message: "Select the mariadb to stop:",
name: "selectedApp",
type: "list",
},
]);
const mariadbId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this mariadb?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("Mariadb stop cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/mariadb.stop`,
{
json: {
mariadbId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this MariaDB instance?",
name: "confirmStop",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error stopping mariadb"));
if (!confirmAnswers.confirmStop) {
this.error(chalk.yellow("MariaDB stop cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mariadb.stop`,
{
json: {
mariadbId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error stopping MariaDB instance"));
}
this.log(chalk.green("MariaDB instance stopped successfully."));
} catch (error: any) {
this.error(chalk.red(`Error stopping MariaDB instance: ${error.message}`));
}
this.log(chalk.green("Mariadb stop successful."));
}
}

View File

@@ -18,114 +18,187 @@ export default class DatabaseMongoCreate extends Command {
description: "ID of the project",
required: false,
}),
name: Flags.string({
char: "n",
description: "Database name",
required: false,
}),
databaseName: Flags.string({
description: "MongoDB database name",
required: false,
}),
description: Flags.string({
char: "d",
description: "Database description",
required: false,
}),
databasePassword: Flags.string({
description: "Database password",
required: false,
}),
databaseUser: Flags.string({
description: "Database user",
default: "mongo",
}),
dockerImage: Flags.string({
description: "Docker image",
default: "mongo:6",
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
appName: Flags.string({
description: "App name",
required: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMongoCreate);
let {
projectId,
name,
databaseName,
description,
databasePassword,
databaseUser,
dockerImage,
appName
} = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !name || !databaseName || !appName || !databasePassword) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
{
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"),
},
]);
try {
const response = await axios.post(
`${auth.url}/api/trpc/mongo.create`,
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
json: {
...dbDetails,
appName: appName.appName,
projectId: project.projectId,
},
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the MongoDB instance in:",
name: "project",
type: "list",
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating MongoDB database"));
}
this.log(
chalk.green(
`MongoDB database '${dbDetails.name}' created successfully.`,
),
);
} catch (error) {
this.error(
// @ts-ignore
chalk.red(`Failed to create MongoDB database: ${error.message}`),
);
]);
projectId = project.projectId;
}
if (!name || !databaseName || !appName || !databasePassword) {
const dbDetails = await inquirer.prompt([
{
message: "Enter the name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: name,
},
{
message: "Database name:",
name: "databaseName",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: databaseName,
},
{
message: "Enter the database description (optional):",
name: "description",
type: "input",
default: description,
},
{
message: "Database password (optional):",
name: "databasePassword",
type: "password",
default: databasePassword,
},
{
default: dockerImage || "mongo:6",
message: "Docker Image (default: mongo:6):",
name: "dockerImage",
type: "input",
},
{
default: databaseUser || "mongo",
message: "Database User: (default: mongo):",
name: "databaseUser",
type: "input",
},
]);
name = dbDetails.name;
databaseName = dbDetails.databaseName;
description = dbDetails.description;
databasePassword = dbDetails.databasePassword;
dockerImage = dbDetails.dockerImage;
databaseUser = dbDetails.databaseUser;
const appNamePrompt = await inquirer.prompt([
{
default: appName || `${slugify(name)}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
appName = appNamePrompt.appName;
}
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this MongoDB instance?',
default: false,
},
]);
if (!confirm.proceed) {
this.error(chalk.yellow("MongoDB creation cancelled."));
return;
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mongo.create`,
{
json: {
name,
databaseName,
description,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating MongoDB instance"));
}
this.log(chalk.green(`MongoDB instance '${name}' created successfully.`));
} catch (error: any) {
this.error(chalk.red(`Error creating MongoDB instance: ${error.message}`));
}
}
}

View File

@@ -20,76 +20,84 @@ export default class DatabaseMongoDelete extends Command {
description: "ID of the project",
required: false,
}),
mongoId: Flags.string({
char: "m",
description: "ID of the MongoDB instance to delete",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMongoDelete);
let { projectId } = flags;
let { projectId, mongoId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mongoId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
if (projects.length === 0) {
this.log(chalk.yellow("No projects found."));
return;
if (!projectId) {
const answers = await inquirer.prompt([
{
choices: projects.map((project) => ({
name: project.name,
value: project.projectId,
})),
message: "Select a project to delete the MongoDB instance from:",
name: "selectedProject",
type: "list",
},
]);
projectId = answers.selectedProject;
}
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",
},
]);
const projectSelected = await getProject(projectId, auth, this);
projectId = answers.selectedProject;
if (!projectSelected.mongo || projectSelected.mongo.length === 0) {
this.error(chalk.yellow("No MongoDB instances found in this project."));
}
if (!mongoId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mongo.map((db) => ({
name: db.name,
value: db.mongoId,
})),
message: "Select the MongoDB instance to delete:",
name: "selectedDb",
type: "list",
},
]);
mongoId = dbAnswers.selectedDb;
}
}
try {
const project = await getProject(projectId, auth, this);
if (!project.mongo || project.mongo.length === 0) {
this.log(chalk.yellow("No MongoDB databases found in this project."));
return;
}
const appAnswers = await inquirer.prompt([
{
choices: project.mongo.map((db: any) => ({
name: db.name,
value: db.mongoId,
})),
message: "Select the MongoDB database to delete:",
name: "selectedApp",
type: "list",
},
]);
const mongoId = appAnswers.selectedApp;
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to delete this MongoDB database?",
message: "Are you sure you want to delete this MongoDB instance?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.log(chalk.yellow("Database deletion cancelled."));
return;
this.error(chalk.yellow("MongoDB deletion cancelled."));
}
}
const deleteResponse = await axios.post(
try {
const response = await axios.post(
`${auth.url}/api/trpc/mongo.remove`,
{
json: {
@@ -104,16 +112,12 @@ export default class DatabaseMongoDelete extends Command {
},
);
if (!deleteResponse.data.result.data.json) {
this.error(chalk.red("Error deleting MongoDB database"));
if (!response.data.result.data.json) {
this.error(chalk.red("Error deleting MongoDB instance"));
}
this.log(chalk.green("MongoDB database deleted successfully."));
} catch (error) {
this.error(
// @ts-ignore
chalk.red(`Failed to delete MongoDB database: ${error.message}`),
);
this.log(chalk.green("MongoDB instance deleted successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deleting MongoDB instance: ${error.message}`));
}
}
}

View File

@@ -1,4 +1,4 @@
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";
@@ -11,79 +11,110 @@ export default class DatabaseMongoDeploy extends Command {
static examples = ["$ <%= config.bin %> app deploy"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
mongoId: Flags.string({
char: "m",
description: "ID of the MongoDB instance to deploy",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMongoDeploy);
let { projectId, mongoId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mongoId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the MongoDB instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the mongo in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.mongo.length === 0) {
this.error(chalk.yellow("No MongoDB instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.mongo.length === 0) {
this.error(chalk.yellow("No mongo found in this project."));
if (!mongoId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mongo.map((db) => ({
name: db.name,
value: db.mongoId,
})),
message: "Select the MongoDB instance to deploy:",
name: "selectedDb",
type: "list",
},
]);
mongoId = dbAnswers.selectedDb;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mongo.map((app) => ({
name: app.name,
value: app.mongoId,
})),
message: "Select the mongo to deploy:",
name: "selectedApp",
type: "list",
},
]);
const mongoId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this mongo?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("mongo deployment cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/mongo.deploy`,
{
json: {
mongoId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this MongoDB instance?",
name: "confirmDeploy",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error deploying mongo"));
if (!confirmAnswers.confirmDeploy) {
this.error(chalk.yellow("MongoDB deployment cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mongo.deploy`,
{
json: {
mongoId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error deploying MongoDB instance"));
}
this.log(chalk.green("MongoDB instance deployed successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deploying MongoDB instance: ${error.message}`));
}
this.log(chalk.green("Mongo deploy successful."));
}
}

View File

@@ -1,4 +1,4 @@
import { Command } from "@oclif/core";
import { Command, Flags } from "@oclif/core";
import chalk from "chalk";
import inquirer from "inquirer";
import axios from "axios";
@@ -11,79 +11,110 @@ export default class DatabaseMongoStop extends Command {
static examples = ["$ <%= config.bin %> mongo stop"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
mongoId: Flags.string({
char: "m",
description: "ID of the MongoDB instance to stop",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMongoStop);
let { projectId, mongoId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mongoId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the MongoDB instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the mongo in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.mongo.length === 0) {
this.error(chalk.yellow("No MongoDB instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.mongo.length === 0) {
this.error(chalk.yellow("No mongo found in this project."));
if (!mongoId) {
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;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mongo.map((app) => ({
name: app.name,
value: app.mongoId,
})),
message: "Select the mongo to stop:",
name: "selectedApp",
type: "list",
},
]);
const mongoId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this mongo?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("mongo stop cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/mongo.stop`,
{
json: {
mongoId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this MongoDB instance?",
name: "confirmStop",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error stopping mongo"));
if (!confirmAnswers.confirmStop) {
this.error(chalk.yellow("MongoDB stop cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mongo.stop`,
{
json: {
mongoId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error stopping MongoDB instance"));
}
this.log(chalk.green("MongoDB instance stopped successfully."));
} catch (error: any) {
this.error(chalk.red(`Error stopping MongoDB instance: ${error.message}`));
}
this.log(chalk.green("Mongo stop successful."));
}
}

View File

@@ -19,119 +19,212 @@ export default class DatabaseMysqlCreate extends Command {
description: "ID of the project",
required: false,
}),
name: Flags.string({
char: "n",
description: "Database name",
required: false,
}),
databaseName: Flags.string({
description: "MySQL database name",
required: false,
}),
description: Flags.string({
char: "d",
description: "Database description",
required: false,
}),
databaseRootPassword: Flags.string({
description: "Database root password",
required: false,
}),
databasePassword: Flags.string({
description: "Database password",
required: false,
}),
databaseUser: Flags.string({
description: "Database user",
default: "mysql",
}),
dockerImage: Flags.string({
description: "Docker image",
default: "mysql:8",
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
appName: Flags.string({
description: "App name",
required: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMysqlCreate);
let {
projectId,
name,
databaseName,
description,
databaseRootPassword,
databasePassword,
databaseUser,
dockerImage,
appName
} = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !name || !databaseName || !appName || !databasePassword || !databaseRootPassword) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
{
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"),
},
]);
try {
const response = await axios.post(
`${auth.url}/api/trpc/mysql.create`,
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
json: {
...dbDetails,
appName: appName.appName,
projectId: project.projectId,
},
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the MySQL instance in:",
name: "project",
type: "list",
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating MySQL database"));
}
this.log(
chalk.green(
`MySQL database '${dbDetails.name}' created successfully.`,
),
);
} catch (error) {
this.error(
// @ts-ignore
chalk.red(`Failed to create MySQL database: ${error.message}`),
);
]);
projectId = project.projectId;
}
if (!name || !databaseName || !appName || !databasePassword || !databaseRootPassword) {
const dbDetails = await inquirer.prompt([
{
message: "Enter the name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: name,
},
{
message: "Database name:",
name: "databaseName",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: databaseName,
},
{
message: "Enter the database description (optional):",
name: "description",
type: "input",
default: description,
},
{
message: "Database Root Password:",
name: "databaseRootPassword",
type: "password",
default: databaseRootPassword,
},
{
message: "Database password:",
name: "databasePassword",
type: "password",
default: databasePassword,
},
{
default: dockerImage || "mysql:8",
message: "Docker Image (default: mysql:8):",
name: "dockerImage",
type: "input",
},
{
default: databaseUser || "mysql",
message: "Database User: (default: mysql):",
name: "databaseUser",
type: "input",
},
]);
name = dbDetails.name;
databaseName = dbDetails.databaseName;
description = dbDetails.description;
databaseRootPassword = dbDetails.databaseRootPassword;
databasePassword = dbDetails.databasePassword;
dockerImage = dbDetails.dockerImage;
databaseUser = dbDetails.databaseUser;
const appNamePrompt = await inquirer.prompt([
{
default: appName || `${slugify(name)}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
appName = appNamePrompt.appName;
}
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this MySQL instance?',
default: false,
},
]);
if (!confirm.proceed) {
this.error(chalk.yellow("MySQL creation cancelled."));
return;
}
}
try {
console.log(JSON.stringify({
name,
databaseName,
description,
databaseRootPassword,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
}, null, 2));
const response = await axios.post(
`${auth.url}/api/trpc/mysql.create`,
{
json: {
name,
databaseName,
description,
databaseRootPassword,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating MySQL instance", response.data.result.data.json));
}
this.log(chalk.green(`MySQL instance '${name}' created successfully.`));
} catch (error: any) {
this.error(chalk.red(`Error creating MySQL instance: ${error.message}`));
}
}
}

View File

@@ -20,79 +20,84 @@ export default class DatabaseMysqlDelete extends Command {
description: "ID of the project",
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<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMysqlDelete);
let { projectId } = flags;
let { projectId, mysqlId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mysqlId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
if (projects.length === 0) {
this.log(chalk.yellow("No projects found."));
return;
if (!projectId) {
const answers = await inquirer.prompt([
{
choices: projects.map((project) => ({
name: project.name,
value: project.projectId,
})),
message: "Select a project to delete the MySQL instance from:",
name: "selectedProject",
type: "list",
},
]);
projectId = answers.selectedProject;
}
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 projectSelected = await getProject(projectId, auth, this);
projectId = answers.selectedProject;
if (!projectSelected.mysql || projectSelected.mysql.length === 0) {
this.error(chalk.yellow("No MySQL instances found in this project."));
}
if (!mysqlId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mysql.map((db) => ({
name: db.name,
value: db.mysqlId,
})),
message: "Select the MySQL instance to delete:",
name: "selectedDb",
type: "list",
},
]);
mysqlId = dbAnswers.selectedDb;
}
}
try {
const project = await getProject(projectId, auth, this);
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: project.mysql.map((app: any) => ({
name: app.name,
value: app.mysqlId,
})),
message: "Select the MySQL database to delete:",
name: "selectedApp",
type: "list",
},
]);
const mysqlId = appAnswers.selectedApp;
// Confirmar eliminación
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
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 MySQL instance?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.log(chalk.yellow("Application deletion cancelled."));
return;
this.error(chalk.yellow("MySQL deletion cancelled."));
}
}
// Eliminar la aplicación seleccionada
const deleteResponse = await axios.post(
try {
const response = await axios.post(
`${auth.url}/api/trpc/mysql.remove`,
{
json: {
@@ -107,14 +112,12 @@ export default class DatabaseMysqlDelete extends Command {
},
);
if (!deleteResponse.data.result.data.json) {
this.error(chalk.red("Error deleting application"));
if (!response.data.result.data.json) {
this.error(chalk.red("Error deleting MySQL instance"));
}
this.log(chalk.green("Application deleted successfully."));
} catch (error) {
// @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError<any>'.
this.error(chalk.red(`Failed to delete application: ${error.message}`));
this.log(chalk.green("MySQL instance deleted successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deleting MySQL instance: ${error.message}`));
}
}
}

View File

@@ -13,77 +13,90 @@ export default class DatabaseMysqlDeploy extends Command {
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMysqlDeploy);
let { projectId, mysqlId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mysqlId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the MySQL instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the mysql in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.mysql.length === 0) {
this.error(chalk.yellow("No MySQL instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.mysql.length === 0) {
this.error(chalk.yellow("No mysql found in this project."));
if (!mysqlId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mysql.map((db) => ({
name: db.name,
value: db.mysqlId,
})),
message: "Select the MySQL instance to deploy:",
name: "selectedDb",
type: "list",
},
]);
mysqlId = dbAnswers.selectedDb;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mysql.map((app) => ({
name: app.name,
value: app.mysqlId,
})),
message: "Select the mysql to deploy:",
name: "selectedApp",
type: "list",
},
]);
const mysqlId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this mysql?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("mysql deployment cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/mysql.deploy`,
{
json: {
mysqlId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this MySQL instance?",
name: "confirmDeploy",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error deploying mysql"));
if (!confirmAnswers.confirmDeploy) {
this.error(chalk.yellow("MySQL deployment cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mysql.deploy`,
{
json: {
mysqlId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error deploying MySQL instance"));
}
this.log(chalk.green("MySQL instance deployed successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deploying MySQL instance: ${error.message}`));
}
this.log(chalk.green("Mysql deployed successful."));
}
}

View File

@@ -13,77 +13,90 @@ export default class DatabaseMysqlStop extends Command {
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseMysqlStop);
let { projectId, mysqlId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !mysqlId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the MySQL instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the mysql in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.mysql.length === 0) {
this.error(chalk.yellow("No MySQL instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.mysql.length === 0) {
this.error(chalk.yellow("No mysql found in this project."));
if (!mysqlId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mysql.map((db) => ({
name: db.name,
value: db.mysqlId,
})),
message: "Select the MySQL instance to stop:",
name: "selectedDb",
type: "list",
},
]);
mysqlId = dbAnswers.selectedDb;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.mysql.map((app) => ({
name: app.name,
value: app.mysqlId,
})),
message: "Select the mysql to stop:",
name: "selectedApp",
type: "list",
},
]);
const mysqlId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this mysql?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("mysql stop cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/mysql.stop`,
{
json: {
mysqlId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this MySQL instance?",
name: "confirmStop",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error stopping mysql"));
if (!confirmAnswers.confirmStop) {
this.error(chalk.yellow("MySQL stop cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/mysql.stop`,
{
json: {
mysqlId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error stopping MySQL instance"));
}
this.log(chalk.green("MySQL instance stopped successfully."));
} catch (error: any) {
this.error(chalk.red(`Error stopping MySQL instance: ${error.message}`));
}
this.log(chalk.green("Mysql stop successful."));
}
}

View File

@@ -17,114 +17,198 @@ export default class DatabasePostgresCreate extends Command {
description: "ID of the project",
required: false,
}),
name: Flags.string({
char: "n",
description: "Database name",
required: false,
}),
databaseName: Flags.string({
description: "PostgreSQL database name",
required: false,
}),
description: Flags.string({
char: "d",
description: "Database description",
required: false,
}),
databasePassword: Flags.string({
description: "Database password",
required: false,
}),
databaseUser: Flags.string({
description: "Database user",
default: "postgres",
}),
dockerImage: Flags.string({
description: "Docker image",
default: "postgres:15",
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
appName: Flags.string({
description: "App name",
required: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabasePostgresCreate);
let {
projectId,
name,
databaseName,
description,
databasePassword,
databaseUser,
dockerImage,
appName
} = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !name || !databaseName || !appName || !databasePassword) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
{
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"),
},
]);
try {
const response = await axios.post(
`${auth.url}/api/trpc/postgres.create`,
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
json: {
...dbDetails,
appName: appName.appName,
projectId: project.projectId,
},
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the PostgreSQL instance in:",
name: "project",
type: "list",
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating PostgreSQL database"));
}
this.log(
chalk.green(
`PostgreSQL database '${dbDetails.name}' created successfully.`,
),
);
} catch (error) {
this.error(
// @ts-ignore
chalk.red(`Failed to create PostgreSQL database: ${error.message}`),
);
]);
projectId = project.projectId;
}
if (!name || !databaseName || !appName || !databasePassword) {
const dbDetails = await inquirer.prompt([
{
message: "Enter the name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: name,
},
{
message: "Database name:",
name: "databaseName",
type: "input",
validate: (input) => (input ? true : "Database name is required"),
default: databaseName,
},
{
message: "Enter the database description (optional):",
name: "description",
type: "input",
default: description,
},
{
message: "Database password:",
name: "databasePassword",
type: "password",
default: databasePassword,
},
{
default: dockerImage || "postgres:15",
message: "Docker Image (default: postgres:15):",
name: "dockerImage",
type: "input",
},
{
default: databaseUser || "postgres",
message: "Database User: (default: postgres):",
name: "databaseUser",
type: "input",
},
]);
name = dbDetails.name;
databaseName = dbDetails.databaseName;
description = dbDetails.description;
databasePassword = dbDetails.databasePassword;
dockerImage = dbDetails.dockerImage;
databaseUser = dbDetails.databaseUser;
const appNamePrompt = await inquirer.prompt([
{
default: appName || `${slugify(name)}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
appName = appNamePrompt.appName;
}
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this PostgreSQL instance?',
default: false,
},
]);
if (!confirm.proceed) {
this.error(chalk.yellow("PostgreSQL creation cancelled."));
return;
}
}
try {
console.log(JSON.stringify({
name,
databaseName,
description,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
}, null, 2));
const response = await axios.post(
`${auth.url}/api/trpc/postgres.create`,
{
json: {
name,
databaseName,
description,
databasePassword,
databaseUser,
dockerImage,
appName,
projectId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating PostgreSQL instance", response.data.result.data.json));
}
this.log(chalk.green(`PostgreSQL instance '${name}' created successfully.`));
} catch (error: any) {
this.error(chalk.red(`Error creating PostgreSQL instance: ${error.message}`));
}
}
}

View File

@@ -20,78 +20,84 @@ export default class DatabasePostgresDelete extends Command {
description: "ID of the project",
required: false,
}),
postgresId: Flags.string({
char: "d",
description: "ID of the PostgreSQL database",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation",
required: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabasePostgresDelete);
let { projectId } = flags;
let { projectId, postgresId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !postgresId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
if (projects.length === 0) {
this.log(chalk.yellow("No projects found."));
return;
if (!projectId) {
const answers = await inquirer.prompt([
{
choices: projects.map((project) => ({
name: project.name,
value: project.projectId,
})),
message: "Select a project to delete the PostgreSQL instance from:",
name: "selectedProject",
type: "list",
},
]);
projectId = answers.selectedProject;
}
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",
},
]);
const projectSelected = await getProject(projectId, auth, this);
projectId = answers.selectedProject;
if (!projectSelected.postgres || projectSelected.postgres.length === 0) {
this.error(chalk.yellow("No PostgreSQL instances found in this project."));
}
if (!postgresId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.postgres.map((db) => ({
name: db.name,
value: db.postgresId,
})),
message: "Select the PostgreSQL instance to delete:",
name: "selectedDb",
type: "list",
},
]);
postgresId = dbAnswers.selectedDb;
}
}
try {
const project = await getProject(projectId, auth, this);
if (!project.postgres || project.postgres.length === 0) {
this.log(
chalk.yellow("No PostgreSQL databases found in this project."),
);
return;
}
const appAnswers = await inquirer.prompt([
{
choices: project.postgres.map((db: any) => ({
name: db.name,
value: db.postgresId,
})),
message: "Select the PostgreSQL database to delete:",
name: "selectedApp",
type: "list",
},
]);
const postgresId = appAnswers.selectedApp;
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to delete this postgres database?",
message: "Are you sure you want to delete this PostgreSQL instance?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.log(chalk.yellow("Database deletion cancelled."));
return;
this.error(chalk.yellow("PostgreSQL deletion cancelled."));
}
}
const deleteResponse = await axios.post(
try {
const response = await axios.post(
`${auth.url}/api/trpc/postgres.remove`,
{
json: {
@@ -106,14 +112,12 @@ export default class DatabasePostgresDelete extends Command {
},
);
if (!deleteResponse.data.result.data.json) {
this.error(chalk.red("Error deleting PostgreSQL database"));
if (!response.data.result.data.json) {
this.error(chalk.red("Error deleting PostgreSQL instance"));
}
this.log(chalk.green("PostgreSQL database deleted successfully."));
} catch (error) {
// @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError<any>'.
this.error(chalk.red(`Failed to delete application: ${error.message}`));
this.log(chalk.green("PostgreSQL instance deleted successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deleting PostgreSQL instance: ${error.message}`));
}
}
}

View File

@@ -1,4 +1,4 @@
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";
@@ -7,83 +7,114 @@ import type { Answers } from "../../app/create.js";
import axios from "axios";
export default class DatabasePostgresDeploy extends Command {
static description = "Deploy an postgres to a project.";
static description = "Deploy a PostgreSQL instance to a project.";
static examples = ["$ <%= config.bin %> app deploy"];
static examples = ["$ <%= config.bin %> postgres deploy"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
postgresId: Flags.string({
char: "d",
description: "ID of the PostgreSQL instance to deploy",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabasePostgresDeploy);
let { projectId, postgresId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !postgresId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the PostgreSQL instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the postgres in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.postgres.length === 0) {
this.error(chalk.yellow("No PostgreSQL instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.postgres.length === 0) {
this.error(chalk.yellow("No postgres found in this project."));
if (!postgresId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.postgres.map((db) => ({
name: db.name,
value: db.postgresId,
})),
message: "Select the PostgreSQL instance to deploy:",
name: "selectedDb",
type: "list",
},
]);
postgresId = dbAnswers.selectedDb;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.postgres.map((app) => ({
name: app.name,
value: app.postgresId,
})),
message: "Select the postgres to deploy:",
name: "selectedApp",
type: "list",
},
]);
const postgresId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this postgres?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("postgres deployment cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/postgres.deploy`,
{
json: {
postgresId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this PostgreSQL instance?",
name: "confirmDeploy",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error deploying postgres"));
if (!confirmAnswers.confirmDeploy) {
this.error(chalk.yellow("PostgreSQL deployment cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/postgres.deploy`,
{
json: {
postgresId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error deploying PostgreSQL instance"));
}
this.log(chalk.green("PostgreSQL instance deployed successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deploying PostgreSQL instance: ${error.message}`));
}
this.log(chalk.green("Postgres deployed successful."));
}
}

View File

@@ -1,89 +1,120 @@
import { Command } from "@oclif/core";
import chalk from "chalk";
import inquirer from "inquirer";
import axios from "axios";
import { getProject, getProjects } from "../../../utils/shared.js";
import { Command, Flags } from "@oclif/core";
import { readAuthConfig } from "../../../utils/utils.js";
import chalk from "chalk";
import { getProject, getProjects } from "../../../utils/shared.js";
import inquirer from "inquirer";
import type { Answers } from "../../app/create.js";
import axios from "axios";
export default class DatabasePostgresStop extends Command {
static description = "Stop an postgres from a project.";
static description = "Stop a PostgreSQL instance in a project.";
static examples = ["$ <%= config.bin %> postgres stop"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
postgresId: Flags.string({
char: "d",
description: "ID of the PostgreSQL instance to stop",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabasePostgresStop);
let { projectId, postgresId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !postgresId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the PostgreSQL instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the postgres in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.postgres.length === 0) {
this.error(chalk.yellow("No PostgreSQL instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.postgres.length === 0) {
this.error(chalk.yellow("No postgres found in this project."));
if (!postgresId) {
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;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.postgres.map((app) => ({
name: app.name,
value: app.postgresId,
})),
message: "Select the postgres to stop:",
name: "selectedApp",
type: "list",
},
]);
const postgresId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this postgres?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("postgres stop cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/postgres.stop`,
{
json: {
postgresId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this PostgreSQL instance?",
name: "confirmStop",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error stopping postgres"));
if (!confirmAnswers.confirmStop) {
this.error(chalk.yellow("PostgreSQL stop cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/postgres.stop`,
{
json: {
postgresId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error stopping PostgreSQL instance"));
}
this.log(chalk.green("PostgreSQL instance stopped successfully."));
} catch (error: any) {
this.error(chalk.red(`Error stopping PostgreSQL instance: ${error.message}`));
}
this.log(chalk.green("Postgres stop successful."));
}
}

View File

@@ -8,7 +8,7 @@ import { getProjects } from "../../../utils/shared.js";
import type { Answers } from "../../app/create.js";
export default class DatabaseRedisCreate extends Command {
static description = "Create a new Redis database within a project.";
static description = "Create a new Redis instance within a project.";
static examples = ["$ <%= config.bin %> redis create"];
@@ -18,102 +18,169 @@ export default class DatabaseRedisCreate extends Command {
description: "ID of the project",
required: false,
}),
name: Flags.string({
char: "n",
description: "Instance name",
required: false,
}),
description: Flags.string({
char: "d",
description: "Instance description",
required: false,
}),
databasePassword: Flags.string({
description: "Redis password",
required: false,
}),
dockerImage: Flags.string({
description: "Docker image",
default: "redis:7",
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
appName: Flags.string({
description: "App name",
required: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseRedisCreate);
let {
projectId,
name,
description,
databasePassword,
dockerImage,
appName
} = flags;
let { projectId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !name || !appName || !databasePassword) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the Redis 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: "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)}-${dbDetails.name}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
try {
const response = await axios.post(
`${auth.url}/api/trpc/redis.create`,
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
json: {
...dbDetails,
appName: appName.appName,
projectId: project.projectId,
},
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to create the Redis instance in:",
name: "project",
type: "list",
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating Redis database"));
}
this.log(
chalk.green(
`Redis database '${dbDetails.name}' created successfully.`,
),
);
} catch (error) {
this.error(
// @ts-ignore
chalk.red(`Failed to create Redis database: ${error.message}`),
);
]);
projectId = project.projectId;
}
if (!name || !appName || !databasePassword) {
const redisDetails = await inquirer.prompt([
{
message: "Enter the name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Instance name is required"),
default: name,
},
{
message: "Enter the instance description (optional):",
name: "description",
type: "input",
default: description,
},
{
message: "Redis password:",
name: "databasePassword",
type: "password",
default: databasePassword,
},
{
default: dockerImage || "redis:7",
message: "Docker Image (default: redis:7):",
name: "dockerImage",
type: "input",
},
]);
name = redisDetails.name;
description = redisDetails.description;
databasePassword = redisDetails.databasePassword;
dockerImage = redisDetails.dockerImage;
const appNamePrompt = await inquirer.prompt([
{
default: appName || `${slugify(name)}`,
message: "Enter the App name:",
name: "appName",
type: "input",
validate: (input) => (input ? true : "App name is required"),
},
]);
appName = appNamePrompt.appName;
}
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this Redis instance?',
default: false,
},
]);
if (!confirm.proceed) {
this.error(chalk.yellow("Redis creation cancelled."));
return;
}
}
try {
console.log(JSON.stringify({
name,
description,
databasePassword,
dockerImage,
appName,
projectId,
}, null, 2));
const response = await axios.post(
`${auth.url}/api/trpc/redis.create`,
{
json: {
name,
description,
databasePassword,
dockerImage,
appName,
projectId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error creating Redis instance", response.data.result.data.json));
}
this.log(chalk.green(`Redis instance '${name}' created successfully.`));
} catch (error: any) {
this.error(chalk.red(`Error creating Redis instance: ${error.message}`));
}
}
}

View File

@@ -1,13 +1,13 @@
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 chalk from "chalk";
import { getProject, getProjects } from "../../../utils/shared.js";
import inquirer from "inquirer";
import type { Answers } from "../../app/create.js";
import axios from "axios";
export default class DatabaseRedisDelete extends Command {
static description = "Delete an redis database from a project.";
static description = "Delete a Redis instance from a project.";
static examples = [
"$ <%= config.bin %> redis delete",
@@ -20,77 +20,84 @@ export default class DatabaseRedisDelete extends Command {
description: "ID of the project",
required: false,
}),
redisId: Flags.string({
char: "r",
description: "ID of the Redis instance to delete",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseRedisDelete);
let { projectId } = flags;
let { projectId, redisId } = flags;
if (!projectId) {
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !redisId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
if (projects.length === 0) {
this.log(chalk.yellow("No projects found."));
return;
if (!projectId) {
const answers = await inquirer.prompt([
{
choices: projects.map((project) => ({
name: project.name,
value: project.projectId,
})),
message: "Select a project to delete the Redis instance from:",
name: "selectedProject",
type: "list",
},
]);
projectId = answers.selectedProject;
}
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",
},
]);
const projectSelected = await getProject(projectId, auth, this);
projectId = answers.selectedProject;
if (!projectSelected.redis || projectSelected.redis.length === 0) {
this.error(chalk.yellow("No Redis instances found in this project."));
}
if (!redisId) {
const dbAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.redis.map((db) => ({
name: db.name,
value: db.redisId,
})),
message: "Select the Redis instance to delete:",
name: "selectedDb",
type: "list",
},
]);
redisId = dbAnswers.selectedDb;
}
}
try {
const project = await getProject(projectId, auth, this);
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: project.redis.map((db: any) => ({
name: db.name,
value: db.redisId,
})),
message: "Select the redis database to delete:",
name: "selectedApp",
type: "list",
},
]);
const redisId = appAnswers.selectedApp;
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to delete this redis database?",
message: "Are you sure you want to delete this Redis instance?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.log(chalk.yellow("Database deletion cancelled."));
return;
this.error(chalk.yellow("Redis deletion cancelled."));
}
}
const deleteResponse = await axios.post(
try {
const response = await axios.post(
`${auth.url}/api/trpc/redis.remove`,
{
json: {
@@ -105,16 +112,12 @@ export default class DatabaseRedisDelete extends Command {
},
);
if (!deleteResponse.data.result.data.json) {
this.error(chalk.red("Error deleting redis database"));
if (!response.data.result.data.json) {
this.error(chalk.red("Error deleting Redis instance"));
}
this.log(chalk.green("Redis database deleted successfully."));
} catch (error) {
this.error(
// @ts-expect-error - TS2339: Property 'data' does not exist on type 'AxiosError<any>'.
chalk.red(`Failed to delete redis database: ${error.message}`),
);
this.log(chalk.green("Redis instance deleted successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deleting Redis instance: ${error.message}`));
}
}
}

View File

@@ -1,4 +1,4 @@
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";
@@ -7,83 +7,114 @@ import type { Answers } from "../../app/create.js";
import axios from "axios";
export default class DatabaseRedisDeploy extends Command {
static description = "Deploy an redis to a project.";
static description = "Deploy a Redis instance to a project.";
static examples = ["$ <%= config.bin %> app deploy"];
static examples = ["$ <%= config.bin %> redis deploy"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
redisId: Flags.string({
char: "r",
description: "ID of the Redis instance to deploy",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseRedisDeploy);
let { projectId, redisId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !redisId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the Redis instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to deploy the redis in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.redis.length === 0) {
this.error(chalk.yellow("No Redis instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.redis.length === 0) {
this.error(chalk.yellow("No redis found in this project."));
if (!redisId) {
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;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.redis.map((app) => ({
name: app.name,
value: app.redisId,
})),
message: "Select the redis to deploy:",
name: "selectedApp",
type: "list",
},
]);
const redisId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this redis?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("redis deployment cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/redis.deploy`,
{
json: {
redisId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to deploy this Redis instance?",
name: "confirmDeploy",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error deploying redis"));
if (!confirmAnswers.confirmDeploy) {
this.error(chalk.yellow("Redis deployment cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/redis.deploy`,
{
json: {
redisId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error deploying Redis instance"));
}
this.log(chalk.green("Redis instance deployed successfully."));
} catch (error: any) {
this.error(chalk.red(`Error deploying Redis instance: ${error.message}`));
}
this.log(chalk.green("Redis deployed successful."));
}
}

View File

@@ -1,89 +1,120 @@
import { Command } from "@oclif/core";
import chalk from "chalk";
import inquirer from "inquirer";
import axios from "axios";
import { getProject, getProjects } from "../../../utils/shared.js";
import { Command, Flags } from "@oclif/core";
import { readAuthConfig } from "../../../utils/utils.js";
import chalk from "chalk";
import { getProject, getProjects } from "../../../utils/shared.js";
import inquirer from "inquirer";
import type { Answers } from "../../app/create.js";
import axios from "axios";
export default class DatabaseRedisStop extends Command {
static description = "Stop an redis from a project.";
static description = "Stop a Redis instance in a project.";
static examples = ["$ <%= config.bin %> redis stop"];
static flags = {
projectId: Flags.string({
char: "p",
description: "ID of the project",
required: false,
}),
redisId: Flags.string({
char: "r",
description: "ID of the Redis instance to stop",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
const { flags } = await this.parse(DatabaseRedisStop);
let { projectId, redisId } = flags;
console.log(chalk.blue.bold("\n Listing all Projects \n"));
// Modo interactivo si no se proporcionan los flags necesarios
if (!projectId || !redisId) {
console.log(chalk.blue.bold("\n Listing all Projects \n"));
const projects = await getProjects(auth, this);
const projects = await getProjects(auth, this);
if (!projectId) {
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the Redis instance from:",
name: "project",
type: "list",
},
]);
projectId = project.projectId;
}
const { project } = await inquirer.prompt<Answers>([
{
choices: projects.map((project) => ({
name: project.name,
value: project,
})),
message: "Select a project to stop the redis in:",
name: "project",
type: "list",
},
]);
const projectSelected = await getProject(projectId, auth, this);
const projectId = project.projectId;
if (projectSelected.redis.length === 0) {
this.error(chalk.yellow("No Redis instances found in this project."));
}
const projectSelected = await getProject(projectId, auth, this);
if (projectSelected.redis.length === 0) {
this.error(chalk.yellow("No redis found in this project."));
if (!redisId) {
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;
}
}
const appAnswers = await inquirer.prompt([
{
// @ts-ignore
choices: projectSelected.redis.map((app) => ({
name: app.name,
value: app.redisId,
})),
message: "Select the redis to stop:",
name: "selectedApp",
type: "list",
},
]);
const redisId = appAnswers.selectedApp;
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this redis?",
name: "confirmDelete",
type: "confirm",
},
]);
if (!confirmAnswers.confirmDelete) {
this.error(chalk.yellow("redis stop cancelled."));
}
const response = await axios.post(
`${auth.url}/api/trpc/redis.stop`,
{
json: {
redisId,
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirmAnswers = await inquirer.prompt([
{
default: false,
message: "Are you sure you want to stop this Redis instance?",
name: "confirmStop",
type: "confirm",
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
]);
if (response.status !== 200) {
this.error(chalk.red("Error stopping redis"));
if (!confirmAnswers.confirmStop) {
this.error(chalk.yellow("Redis stop cancelled."));
}
}
try {
const response = await axios.post(
`${auth.url}/api/trpc/redis.stop`,
{
json: {
redisId,
},
},
{
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
},
);
if (response.status !== 200) {
this.error(chalk.red("Error stopping Redis instance"));
}
this.log(chalk.green("Redis instance stopped successfully."));
} catch (error: any) {
this.error(chalk.red(`Error stopping Redis instance: ${error.message}`));
}
this.log(chalk.green("Redis stop successful."));
}
}

View File

@@ -1,76 +1,91 @@
import { Command, Flags } from "@oclif/core";
import axios from "axios";
import chalk from "chalk";
import inquirer, { type Answers, type QuestionCollection } from "inquirer";
import inquirer from "inquirer";
import { readAuthConfig } from "../../utils/utils.js";
export default class ProjectCreate extends Command {
static override description =
"Create a new project with an optional description.";
static description = "Create a new project.";
static override examples = [
"$ <%= config.bin %> <%= command.id %> -n MyProject -d 'This is my project description'",
"$ <%= config.bin %> <%= command.id %> -n MyProject",
"$ <%= config.bin %> <%= command.id %>",
static examples = [
"$ <%= config.bin %> project create",
"$ <%= config.bin %> project create -n MyProject -d 'Project description'",
"$ <%= config.bin %> project create --name MyProject --skipConfirm",
];
static override flags = {
description: Flags.string({
char: "d",
description: "Description of the project",
required: false,
}),
static flags = {
name: Flags.string({
char: "n",
description: "Name of the project",
required: false,
}),
description: Flags.string({
char: "d",
description: "Description of the project",
required: false,
}),
skipConfirm: Flags.boolean({
char: "y",
description: "Skip confirmation prompt",
default: false,
}),
};
public async run(): Promise<void> {
const auth = await readAuthConfig(this);
console.log(chalk.blue.bold("\n Create a New Project \n"));
const { flags } = await this.parse(ProjectCreate);
let { name, description } = flags;
let answers: Answers = {};
// Modo interactivo si no se proporcionan los flags necesarios
if (!name) {
const answers = await inquirer.prompt([
{
message: "Enter the project name:",
name: "name",
type: "input",
validate: (input) => (input ? true : "Project name is required"),
},
{
message: "Enter the project description (optional):",
name: "description",
type: "input",
default: description || "",
},
]);
const questions: QuestionCollection[] = [];
if (!flags.name) {
questions.push({
message: chalk.green("Enter the project name:"),
name: "name",
type: "input",
validate: (input) => (input ? true : "Project name is required"),
});
name = answers.name;
description = answers.description;
}
if (!flags.description) {
questions.push({
default: "",
message: chalk.green("Enter the project description (optional):"),
name: "description",
type: "input",
});
}
// Confirmar si no se especifica --skipConfirm
if (!flags.skipConfirm) {
const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'proceed',
message: 'Do you want to create this project?',
default: false,
},
]);
if (questions.length > 0) {
answers = await inquirer.prompt(questions);
if (!confirm.proceed) {
this.error(chalk.yellow("Project creation cancelled."));
return;
}
}
const name = flags.name || answers.name;
const description = flags.description || answers.description;
try {
console.log(JSON.stringify({
name,
description,
}, null, 2));
const response = await axios.post(
`${auth.url}/api/trpc/project.create`,
{
json: {
description,
name,
description,
},
},
{
@@ -82,13 +97,12 @@ export default class ProjectCreate extends Command {
);
if (!response.data.result.data.json) {
this.error(chalk.red("Error`"));
this.error(chalk.red("Error creating project", response.data.result.data.json));
}
this.log(chalk.green(`Project '${name}' created successfully.`));
} catch (error) {
// @ts-expect-error hola
this.error(chalk.red(`Failed to create project: ${error.message}`));
} catch (error: any) {
this.error(chalk.red(`Error creating project: ${error.message}`));
}
}
}

View File

@@ -15,10 +15,19 @@ export type AuthConfig = {
};
export const readAuthConfig = async (command: Command): Promise<AuthConfig> => {
// Primero intentar leer desde variables de entorno
const envToken = process.env.DOKPLOY_AUTH_TOKEN;
const envUrl = process.env.DOKPLOY_URL;
if (envToken && envUrl) {
return { token: envToken, url: envUrl };
}
// Si no hay variables de entorno, usar el archivo de configuración
if (!fs.existsSync(configPath)) {
command.error(
chalk.red(
"No configuration file found. Please authenticate first using the 'authenticate' command.",
"No configuration file found and no environment variables set. Please authenticate first using the 'authenticate' command or set DOKPLOY_URL and DOKPLOY_AUTH_TOKEN environment variables.",
),
);
}
@@ -30,7 +39,7 @@ export const readAuthConfig = async (command: Command): Promise<AuthConfig> => {
if (!url || !token) {
command.error(
chalk.red(
"Incomplete authentication details. Please authenticate again using the 'authenticate' command.",
"Incomplete authentication details. Please authenticate again using the 'authenticate' command or set environment variables.",
),
);
}