@barekey/cli 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -12
- package/bun.lock +9 -3
- package/dist/auth-provider.js +7 -4
- package/dist/command-utils.js +6 -6
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.js +47 -0
- package/dist/commands/auth.js +31 -9
- package/dist/commands/billing.d.ts +2 -0
- package/dist/commands/billing.js +59 -0
- package/dist/commands/env.js +157 -125
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +32 -0
- package/dist/commands/org.d.ts +2 -0
- package/dist/commands/org.js +85 -0
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.js +99 -0
- package/dist/commands/stage.d.ts +2 -0
- package/dist/commands/stage.js +125 -0
- package/dist/commands/target-prompts.d.ts +184 -0
- package/dist/commands/target-prompts.js +312 -0
- package/dist/commands/typegen.d.ts +2 -2
- package/dist/commands/typegen.js +57 -32
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/context/session-id.d.ts +11 -0
- package/dist/context/session-id.js +14 -0
- package/dist/contracts/index.d.ts +499 -0
- package/dist/contracts/index.js +313 -0
- package/dist/credentials-store.js +70 -11
- package/dist/http.d.ts +34 -0
- package/dist/http.js +56 -2
- package/dist/index.js +12 -0
- package/dist/runtime-config.js +14 -26
- package/dist/typegen/core.d.ts +45 -0
- package/dist/typegen/core.js +219 -0
- package/dist/types.d.ts +5 -3
- package/package.json +2 -2
- package/src/auth-provider.ts +8 -5
- package/src/command-utils.ts +6 -6
- package/src/commands/audit.ts +63 -0
- package/src/commands/auth.ts +45 -39
- package/src/commands/billing.ts +70 -0
- package/src/commands/env.ts +211 -218
- package/src/commands/init.ts +47 -0
- package/src/commands/org.ts +104 -0
- package/src/commands/project.ts +130 -0
- package/src/commands/stage.ts +167 -0
- package/src/commands/target-prompts.ts +357 -0
- package/src/commands/typegen.ts +71 -45
- package/src/constants.ts +1 -1
- package/src/context/session-id.ts +14 -0
- package/src/contracts/index.ts +376 -0
- package/src/credentials-store.ts +86 -12
- package/src/http.ts +78 -2
- package/src/index.ts +12 -0
- package/src/runtime-config.ts +19 -32
- package/src/typegen/core.ts +311 -0
- package/src/types.ts +5 -3
- package/test/command-utils.test.ts +47 -0
- package/test/credentials-store.test.ts +40 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
|
|
6
|
+
import { type EnvTargetOptions } from "../command-utils.js";
|
|
7
|
+
import {
|
|
8
|
+
promptForOrganizationSlug,
|
|
9
|
+
promptForProjectSlug,
|
|
10
|
+
promptForStageSlug,
|
|
11
|
+
} from "./target-prompts.js";
|
|
12
|
+
|
|
13
|
+
async function runInit(options: EnvTargetOptions & { path?: string }) {
|
|
14
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
15
|
+
const projectSlug = await promptForProjectSlug(orgSlug, options.project);
|
|
16
|
+
const stageSlug = await promptForStageSlug(orgSlug, projectSlug, options.stage);
|
|
17
|
+
const configPath = path.resolve(options.path?.trim() || "barekey.json");
|
|
18
|
+
const contents = `${JSON.stringify(
|
|
19
|
+
{
|
|
20
|
+
organization: orgSlug,
|
|
21
|
+
project: projectSlug,
|
|
22
|
+
environment: stageSlug,
|
|
23
|
+
config: {
|
|
24
|
+
mode: "centralized",
|
|
25
|
+
typegen: "semantic",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
null,
|
|
29
|
+
2,
|
|
30
|
+
)}\n`;
|
|
31
|
+
|
|
32
|
+
await writeFile(configPath, contents, "utf8");
|
|
33
|
+
console.log(`Wrote ${configPath}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function registerInitCommand(program: Command): void {
|
|
37
|
+
program
|
|
38
|
+
.command("init")
|
|
39
|
+
.description("Create or update barekey.json for the current repo")
|
|
40
|
+
.option("--org <slug>", "Organization slug")
|
|
41
|
+
.option("--project <slug>", "Project slug")
|
|
42
|
+
.option("--stage <slug>", "Stage slug")
|
|
43
|
+
.option("--path <path>", "Config path", "barekey.json")
|
|
44
|
+
.action(async (options: EnvTargetOptions & { path?: string }) => {
|
|
45
|
+
await runInit(options);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { text, isCancel, cancel } from "@clack/prompts";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
import { createCliAuthProvider } from "../auth-provider.js";
|
|
5
|
+
import { requireLocalSession, toJsonOutput } from "../command-utils.js";
|
|
6
|
+
import { OrganizationsResponseSchema } from "../contracts/index.js";
|
|
7
|
+
import { getJson, postJson } from "../http.js";
|
|
8
|
+
|
|
9
|
+
async function promptForName(name: string | undefined): Promise<string> {
|
|
10
|
+
const existing = name?.trim();
|
|
11
|
+
if (existing && existing.length > 0) {
|
|
12
|
+
return existing;
|
|
13
|
+
}
|
|
14
|
+
if (!process.stdout.isTTY) {
|
|
15
|
+
throw new Error("Organization name is required in non-interactive mode.");
|
|
16
|
+
}
|
|
17
|
+
const prompted = await text({
|
|
18
|
+
message: "What’s the name of this organization?",
|
|
19
|
+
validate: (value) => (value.trim().length > 0 ? undefined : "Name is required."),
|
|
20
|
+
});
|
|
21
|
+
if (isCancel(prompted)) {
|
|
22
|
+
cancel("Command canceled.");
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
return prompted.trim();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function runOrgList(options: { json?: boolean }) {
|
|
29
|
+
const local = await requireLocalSession();
|
|
30
|
+
const authProvider = createCliAuthProvider();
|
|
31
|
+
const accessToken = await authProvider.getAccessToken();
|
|
32
|
+
const response = await getJson({
|
|
33
|
+
baseUrl: local.baseUrl,
|
|
34
|
+
path: "/v1/cli/orgs",
|
|
35
|
+
accessToken,
|
|
36
|
+
schema: OrganizationsResponseSchema,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (options.json) {
|
|
40
|
+
toJsonOutput(true, response.organizations);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (response.organizations.length === 0) {
|
|
45
|
+
console.log("No organizations found.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (const organization of response.organizations) {
|
|
50
|
+
console.log(`${organization.name} (${organization.slug}) ${organization.role}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function runOrgCreate(
|
|
55
|
+
name: string | undefined,
|
|
56
|
+
options: {
|
|
57
|
+
slug?: string;
|
|
58
|
+
json?: boolean;
|
|
59
|
+
},
|
|
60
|
+
) {
|
|
61
|
+
const resolvedName = await promptForName(name);
|
|
62
|
+
const local = await requireLocalSession();
|
|
63
|
+
const authProvider = createCliAuthProvider();
|
|
64
|
+
const accessToken = await authProvider.getAccessToken();
|
|
65
|
+
const response = await postJson({
|
|
66
|
+
baseUrl: local.baseUrl,
|
|
67
|
+
path: "/v1/cli/orgs/create",
|
|
68
|
+
accessToken,
|
|
69
|
+
payload: {
|
|
70
|
+
name: resolvedName,
|
|
71
|
+
slug: options.slug?.trim() || null,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (options.json) {
|
|
76
|
+
toJsonOutput(true, response);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const organization = (response as { organization: { name: string; slug: string } }).organization;
|
|
81
|
+
console.log(`Created organization ${organization.name} (${organization.slug}).`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function registerOrgCommands(program: Command): void {
|
|
85
|
+
const org = program.command("org").description("Organization management");
|
|
86
|
+
|
|
87
|
+
org
|
|
88
|
+
.command("list")
|
|
89
|
+
.description("List organizations available to the current user")
|
|
90
|
+
.option("--json", "Machine-readable output", false)
|
|
91
|
+
.action(async (options: { json?: boolean }) => {
|
|
92
|
+
await runOrgList(options);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
org
|
|
96
|
+
.command("create")
|
|
97
|
+
.description("Create an organization")
|
|
98
|
+
.argument("[name]", "Organization name")
|
|
99
|
+
.option("--slug <slug>", "Organization slug")
|
|
100
|
+
.option("--json", "Machine-readable output", false)
|
|
101
|
+
.action(async (name: string | undefined, options: { slug?: string; json?: boolean }) => {
|
|
102
|
+
await runOrgCreate(name, options);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { cancel, confirm, isCancel, text } from "@clack/prompts";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
import { toJsonOutput, type EnvTargetOptions } from "../command-utils.js";
|
|
5
|
+
import {
|
|
6
|
+
createProjectForOrganization,
|
|
7
|
+
deleteProjectForOrganization,
|
|
8
|
+
listProjectsForOrganization,
|
|
9
|
+
promptForOrganizationSlug,
|
|
10
|
+
promptForProjectSlug,
|
|
11
|
+
} from "./target-prompts.js";
|
|
12
|
+
|
|
13
|
+
async function promptForProjectName(name: string | undefined): Promise<string> {
|
|
14
|
+
const existing = name?.trim();
|
|
15
|
+
if (existing && existing.length > 0) {
|
|
16
|
+
return existing;
|
|
17
|
+
}
|
|
18
|
+
if (!process.stdout.isTTY) {
|
|
19
|
+
throw new Error("Project name is required in non-interactive mode.");
|
|
20
|
+
}
|
|
21
|
+
const prompted = await text({
|
|
22
|
+
message: "What’s the name of this project?",
|
|
23
|
+
validate: (value) => (value.trim().length > 0 ? undefined : "Project name is required."),
|
|
24
|
+
});
|
|
25
|
+
if (isCancel(prompted)) {
|
|
26
|
+
cancel("Command canceled.");
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
return prompted.trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function runProjectList(options: EnvTargetOptions & { json?: boolean }) {
|
|
33
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
34
|
+
const projects = await listProjectsForOrganization(orgSlug);
|
|
35
|
+
|
|
36
|
+
if (options.json) {
|
|
37
|
+
toJsonOutput(true, projects);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (projects.length === 0) {
|
|
42
|
+
console.log("No projects found.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const project of projects) {
|
|
47
|
+
console.log(`${project.name} (${project.slug}) secrets=${project.secretCount}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function runProjectCreate(
|
|
52
|
+
name: string | undefined,
|
|
53
|
+
options: EnvTargetOptions & { json?: boolean },
|
|
54
|
+
) {
|
|
55
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
56
|
+
const projectName = await promptForProjectName(name);
|
|
57
|
+
const project = await createProjectForOrganization(orgSlug, projectName);
|
|
58
|
+
|
|
59
|
+
if (options.json) {
|
|
60
|
+
toJsonOutput(true, project);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(`Created project ${project.name} (${project.slug}).`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function registerProjectCommands(program: Command): void {
|
|
68
|
+
const project = program.command("project").description("Project management");
|
|
69
|
+
|
|
70
|
+
project
|
|
71
|
+
.command("list")
|
|
72
|
+
.description("List projects in an organization")
|
|
73
|
+
.option("--org <slug>", "Organization slug")
|
|
74
|
+
.option("--json", "Machine-readable output", false)
|
|
75
|
+
.action(async (options: EnvTargetOptions & { json?: boolean }) => {
|
|
76
|
+
await runProjectList(options);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
project
|
|
80
|
+
.command("create")
|
|
81
|
+
.description("Create a project")
|
|
82
|
+
.argument("[name]", "Project name")
|
|
83
|
+
.option("--org <slug>", "Organization slug")
|
|
84
|
+
.option("--json", "Machine-readable output", false)
|
|
85
|
+
.action(async (name: string | undefined, options: EnvTargetOptions & { json?: boolean }) => {
|
|
86
|
+
await runProjectCreate(name, options);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
project
|
|
90
|
+
.command("delete")
|
|
91
|
+
.description("Delete a project")
|
|
92
|
+
.argument("[slug]", "Project slug")
|
|
93
|
+
.option("--org <slug>", "Organization slug")
|
|
94
|
+
.option("--yes", "Skip confirmation prompt", false)
|
|
95
|
+
.option("--json", "Machine-readable output", false)
|
|
96
|
+
.action(
|
|
97
|
+
async (
|
|
98
|
+
slug: string | undefined,
|
|
99
|
+
options: EnvTargetOptions & { yes?: boolean; json?: boolean },
|
|
100
|
+
) => {
|
|
101
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
102
|
+
const projectSlug = await promptForProjectSlug(orgSlug, slug);
|
|
103
|
+
|
|
104
|
+
if (!options.yes) {
|
|
105
|
+
if (!process.stdout.isTTY) {
|
|
106
|
+
throw new Error("Project deletion requires --yes in non-interactive mode.");
|
|
107
|
+
}
|
|
108
|
+
const confirmed = await confirm({
|
|
109
|
+
message: `Delete project ${projectSlug}?`,
|
|
110
|
+
initialValue: false,
|
|
111
|
+
});
|
|
112
|
+
if (isCancel(confirmed)) {
|
|
113
|
+
cancel("Command canceled.");
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
if (!confirmed) {
|
|
117
|
+
throw new Error("Delete canceled.");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const response = await deleteProjectForOrganization(orgSlug, projectSlug);
|
|
122
|
+
if (options.json) {
|
|
123
|
+
toJsonOutput(true, response);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(`Deleted project ${response.deletedProjectSlug}.`);
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { cancel, confirm, isCancel, text } from "@clack/prompts";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
import { toJsonOutput, type EnvTargetOptions } from "../command-utils.js";
|
|
5
|
+
import {
|
|
6
|
+
createStageForProject,
|
|
7
|
+
deleteStageForProject,
|
|
8
|
+
listStagesForProject,
|
|
9
|
+
promptForOrganizationSlug,
|
|
10
|
+
promptForProjectSlug,
|
|
11
|
+
promptForStageSlug,
|
|
12
|
+
renameStageForProject,
|
|
13
|
+
} from "./target-prompts.js";
|
|
14
|
+
|
|
15
|
+
async function promptForStageName(name: string | undefined): Promise<string> {
|
|
16
|
+
const existing = name?.trim();
|
|
17
|
+
if (existing && existing.length > 0) {
|
|
18
|
+
return existing;
|
|
19
|
+
}
|
|
20
|
+
if (!process.stdout.isTTY) {
|
|
21
|
+
throw new Error("Stage name is required in non-interactive mode.");
|
|
22
|
+
}
|
|
23
|
+
const prompted = await text({
|
|
24
|
+
message: "What’s the name of this stage?",
|
|
25
|
+
validate: (value) => (value.trim().length > 0 ? undefined : "Stage name is required."),
|
|
26
|
+
});
|
|
27
|
+
if (isCancel(prompted)) {
|
|
28
|
+
cancel("Command canceled.");
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
return prompted.trim();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function runStageList(options: EnvTargetOptions & { json?: boolean }) {
|
|
35
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
36
|
+
const projectSlug = await promptForProjectSlug(orgSlug, options.project);
|
|
37
|
+
const stages = await listStagesForProject(orgSlug, projectSlug);
|
|
38
|
+
|
|
39
|
+
if (options.json) {
|
|
40
|
+
toJsonOutput(true, stages);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (stages.length === 0) {
|
|
45
|
+
console.log("No stages found.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (const stage of stages) {
|
|
50
|
+
console.log(`${stage.name} (${stage.slug}) variables=${stage.variableCount}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function runStageCreate(
|
|
55
|
+
name: string | undefined,
|
|
56
|
+
options: EnvTargetOptions & { json?: boolean },
|
|
57
|
+
) {
|
|
58
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
59
|
+
const projectSlug = await promptForProjectSlug(orgSlug, options.project);
|
|
60
|
+
const stageName = await promptForStageName(name);
|
|
61
|
+
const stage = await createStageForProject(orgSlug, projectSlug, stageName);
|
|
62
|
+
|
|
63
|
+
if (options.json) {
|
|
64
|
+
toJsonOutput(true, stage);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log(`Created stage ${stage.name} (${stage.slug}).`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function registerStageCommands(program: Command): void {
|
|
72
|
+
const stage = program.command("stage").description("Stage management");
|
|
73
|
+
|
|
74
|
+
stage
|
|
75
|
+
.command("list")
|
|
76
|
+
.description("List stages in a project")
|
|
77
|
+
.option("--org <slug>", "Organization slug")
|
|
78
|
+
.option("--project <slug>", "Project slug")
|
|
79
|
+
.option("--json", "Machine-readable output", false)
|
|
80
|
+
.action(async (options: EnvTargetOptions & { json?: boolean }) => {
|
|
81
|
+
await runStageList(options);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
stage
|
|
85
|
+
.command("create")
|
|
86
|
+
.description("Create a stage")
|
|
87
|
+
.argument("[name]", "Stage name")
|
|
88
|
+
.option("--org <slug>", "Organization slug")
|
|
89
|
+
.option("--project <slug>", "Project slug")
|
|
90
|
+
.option("--json", "Machine-readable output", false)
|
|
91
|
+
.action(async (name: string | undefined, options: EnvTargetOptions & { json?: boolean }) => {
|
|
92
|
+
await runStageCreate(name, options);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
stage
|
|
96
|
+
.command("rename")
|
|
97
|
+
.description("Rename a stage")
|
|
98
|
+
.argument("[slug]", "Stage slug")
|
|
99
|
+
.argument("[name]", "New stage display name")
|
|
100
|
+
.option("--org <slug>", "Organization slug")
|
|
101
|
+
.option("--project <slug>", "Project slug")
|
|
102
|
+
.option("--json", "Machine-readable output", false)
|
|
103
|
+
.action(
|
|
104
|
+
async (
|
|
105
|
+
slug: string | undefined,
|
|
106
|
+
name: string | undefined,
|
|
107
|
+
options: EnvTargetOptions & { json?: boolean },
|
|
108
|
+
) => {
|
|
109
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
110
|
+
const projectSlug = await promptForProjectSlug(orgSlug, options.project);
|
|
111
|
+
const stageSlug = await promptForStageSlug(orgSlug, projectSlug, slug);
|
|
112
|
+
const stageName = await promptForStageName(name);
|
|
113
|
+
const stage = await renameStageForProject(orgSlug, projectSlug, stageSlug, stageName);
|
|
114
|
+
|
|
115
|
+
if (options.json) {
|
|
116
|
+
toJsonOutput(true, stage);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(`Renamed stage ${stage.slug} to ${stage.name}.`);
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
stage
|
|
125
|
+
.command("delete")
|
|
126
|
+
.description("Delete a stage")
|
|
127
|
+
.argument("[slug]", "Stage slug")
|
|
128
|
+
.option("--org <slug>", "Organization slug")
|
|
129
|
+
.option("--project <slug>", "Project slug")
|
|
130
|
+
.option("--yes", "Skip confirmation prompt", false)
|
|
131
|
+
.option("--json", "Machine-readable output", false)
|
|
132
|
+
.action(
|
|
133
|
+
async (
|
|
134
|
+
slug: string | undefined,
|
|
135
|
+
options: EnvTargetOptions & { yes?: boolean; json?: boolean },
|
|
136
|
+
) => {
|
|
137
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
138
|
+
const projectSlug = await promptForProjectSlug(orgSlug, options.project);
|
|
139
|
+
const stageSlug = await promptForStageSlug(orgSlug, projectSlug, slug);
|
|
140
|
+
|
|
141
|
+
if (!options.yes) {
|
|
142
|
+
if (!process.stdout.isTTY) {
|
|
143
|
+
throw new Error("Stage deletion requires --yes in non-interactive mode.");
|
|
144
|
+
}
|
|
145
|
+
const confirmed = await confirm({
|
|
146
|
+
message: `Delete stage ${stageSlug}?`,
|
|
147
|
+
initialValue: false,
|
|
148
|
+
});
|
|
149
|
+
if (isCancel(confirmed)) {
|
|
150
|
+
cancel("Command canceled.");
|
|
151
|
+
process.exit(0);
|
|
152
|
+
}
|
|
153
|
+
if (!confirmed) {
|
|
154
|
+
throw new Error("Delete canceled.");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const response = await deleteStageForProject(orgSlug, projectSlug, stageSlug);
|
|
159
|
+
if (options.json) {
|
|
160
|
+
toJsonOutput(true, response);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log(`Deleted stage ${response.deletedStageSlug}.`);
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
}
|