Skip to content

Commit f95d33c

Browse files
committed
feat: add environment creation and deletion commands
- Introduced EnvironmentCreate and EnvironmentDelete commands for managing environments within projects. - Implemented interactive prompts for selecting projects and environments if flags are not provided. - Added flags for projectId, environmentId, name, description, and skipConfirm to enhance command flexibility. - Improved error handling for environment creation and deletion processes.
1 parent a7a5e2e commit f95d33c

File tree

2 files changed

+260
-0
lines changed

2 files changed

+260
-0
lines changed

src/commands/environment/create.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { Command, Flags } from "@oclif/core";
2+
import axios from "axios";
3+
import chalk from "chalk";
4+
import inquirer from "inquirer";
5+
6+
import { getProjects } from "../../utils/shared.js";
7+
import { readAuthConfig } from "../../utils/utils.js";
8+
import type { Answers } from "../app/create.js";
9+
10+
export default class EnvironmentCreate extends Command {
11+
static description = "Create a new environment within a project.";
12+
13+
static examples = ["$ <%= config.bin %> environment create"];
14+
15+
static flags = {
16+
projectId: Flags.string({
17+
char: "p",
18+
description: "ID of the project",
19+
required: false,
20+
}),
21+
name: Flags.string({
22+
char: "n",
23+
description: "Environment name",
24+
required: false,
25+
}),
26+
description: Flags.string({
27+
char: "d",
28+
description: "Environment description",
29+
required: false,
30+
}),
31+
skipConfirm: Flags.boolean({
32+
char: "y",
33+
description: "Skip confirmation prompt",
34+
default: false,
35+
}),
36+
};
37+
38+
public async run(): Promise<void> {
39+
const auth = await readAuthConfig(this);
40+
const { flags } = await this.parse(EnvironmentCreate);
41+
let { projectId, name, description } = flags;
42+
43+
// Modo interactivo si no se proporcionan los flags necesarios
44+
if (!projectId || !name) {
45+
console.log(chalk.blue.bold("\n Listing all Projects \n"));
46+
const projects = await getProjects(auth, this);
47+
48+
// 1. Seleccionar proyecto
49+
if (!projectId) {
50+
const { project } = await inquirer.prompt<Answers>([
51+
{
52+
choices: projects.map((project) => ({
53+
name: project.name,
54+
value: project,
55+
})),
56+
message: "Select a project to create the environment in:",
57+
name: "project",
58+
type: "list",
59+
},
60+
]);
61+
projectId = project.projectId;
62+
}
63+
64+
// 2. Ingresar detalles del environment
65+
if (!name) {
66+
const envDetails = await inquirer.prompt([
67+
{
68+
message: "Enter the environment name:",
69+
name: "name",
70+
type: "input",
71+
validate: (input) => (input ? true : "Environment name is required"),
72+
default: name,
73+
},
74+
{
75+
message: "Enter the environment description (optional):",
76+
name: "description",
77+
type: "input",
78+
default: description,
79+
},
80+
]);
81+
82+
name = envDetails.name;
83+
description = envDetails.description;
84+
}
85+
}
86+
87+
// Confirmar si no se especifica --skipConfirm
88+
if (!flags.skipConfirm) {
89+
const confirm = await inquirer.prompt([
90+
{
91+
type: 'confirm',
92+
name: 'proceed',
93+
message: 'Do you want to create this environment?',
94+
default: false,
95+
},
96+
]);
97+
98+
if (!confirm.proceed) {
99+
this.error(chalk.yellow("Environment creation cancelled."));
100+
return;
101+
}
102+
}
103+
104+
try {
105+
const response = await axios.post(
106+
`${auth.url}/api/trpc/environment.create`,
107+
{
108+
json: {
109+
name,
110+
description,
111+
projectId,
112+
},
113+
},
114+
{
115+
headers: {
116+
"x-api-key": auth.token,
117+
"Content-Type": "application/json",
118+
},
119+
},
120+
);
121+
122+
if (!response.data.result.data.json) {
123+
this.error(chalk.red("Error creating environment"));
124+
}
125+
126+
this.log(chalk.green(`Environment '${name}' created successfully.`));
127+
} catch (error: any) {
128+
this.error(chalk.red(`Error creating environment: ${error.message}`));
129+
}
130+
}
131+
}

src/commands/environment/delete.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { Command, Flags } from "@oclif/core";
2+
import axios from "axios";
3+
import chalk from "chalk";
4+
import inquirer from "inquirer";
5+
6+
import { getProjects } from "../../utils/shared.js";
7+
import { readAuthConfig } from "../../utils/utils.js";
8+
import type { Answers } from "../app/create.js";
9+
10+
export default class EnvironmentDelete extends Command {
11+
static description = "Delete an environment from a project.";
12+
13+
static examples = [
14+
"$ <%= config.bin %> environment delete",
15+
"$ <%= config.bin %> environment delete -p <projectId>",
16+
];
17+
18+
static flags = {
19+
projectId: Flags.string({
20+
char: "p",
21+
description: "ID of the project",
22+
required: false,
23+
}),
24+
environmentId: Flags.string({
25+
char: "e",
26+
description: "ID of the environment to delete",
27+
required: false,
28+
}),
29+
skipConfirm: Flags.boolean({
30+
char: "y",
31+
description: "Skip confirmation prompt",
32+
default: false,
33+
}),
34+
};
35+
36+
public async run(): Promise<void> {
37+
const auth = await readAuthConfig(this);
38+
const { flags } = await this.parse(EnvironmentDelete);
39+
let { projectId, environmentId } = flags;
40+
41+
// Modo interactivo si no se proporcionan los flags necesarios
42+
if (!projectId || !environmentId) {
43+
console.log(chalk.blue.bold("\n Listing all Projects \n"));
44+
const projects = await getProjects(auth, this);
45+
46+
let selectedProject;
47+
48+
// 1. Seleccionar proyecto
49+
if (!projectId) {
50+
const { project } = await inquirer.prompt<Answers>([
51+
{
52+
choices: projects.map((project) => ({
53+
name: project.name,
54+
value: project,
55+
})),
56+
message: "Select a project to delete the environment from:",
57+
name: "project",
58+
type: "list",
59+
},
60+
]);
61+
selectedProject = project;
62+
projectId = project.projectId;
63+
} else {
64+
selectedProject = projects.find(p => p.projectId === projectId);
65+
}
66+
67+
// 2. Seleccionar environment del proyecto
68+
if (!environmentId) {
69+
if (!selectedProject?.environments || selectedProject.environments.length === 0) {
70+
this.error(chalk.yellow("No environments found in this project."));
71+
}
72+
73+
const { environment } = await inquirer.prompt([
74+
{
75+
choices: selectedProject.environments.map((env) => ({
76+
name: `${env.name} (${env.description})`,
77+
value: env,
78+
})),
79+
message: "Select an environment to delete:",
80+
name: "environment",
81+
type: "list",
82+
},
83+
]);
84+
environmentId = environment.environmentId;
85+
}
86+
}
87+
88+
// Confirmar si no se especifica --skipConfirm
89+
if (!flags.skipConfirm) {
90+
const confirmAnswers = await inquirer.prompt([
91+
{
92+
default: false,
93+
message: "Are you sure you want to delete this environment? This action cannot be undone.",
94+
name: "confirmDelete",
95+
type: "confirm",
96+
},
97+
]);
98+
99+
if (!confirmAnswers.confirmDelete) {
100+
this.error(chalk.yellow("Environment deletion cancelled."));
101+
}
102+
}
103+
104+
try {
105+
const response = await axios.post(
106+
`${auth.url}/api/trpc/environment.remove`,
107+
{
108+
json: {
109+
environmentId,
110+
},
111+
},
112+
{
113+
headers: {
114+
"x-api-key": auth.token,
115+
"Content-Type": "application/json",
116+
},
117+
},
118+
);
119+
120+
if (!response.data.result.data.json) {
121+
this.error(chalk.red("Error deleting environment"));
122+
}
123+
124+
this.log(chalk.green("Environment deleted successfully."));
125+
} catch (error: any) {
126+
this.error(chalk.red(`Error deleting environment: ${error.message}`));
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)