-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdelete.ts
179 lines (153 loc) · 5.51 KB
/
delete.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import { Args, Flags } from '@oclif/core'
import * as readline from 'node:readline'
import { ControlBaseCommand } from '../../control-base-command.js'
import AppsSwitch from './switch.js'
export default class AppsDeleteCommand extends ControlBaseCommand {
static args = {
id: Args.string({
description: 'App ID to delete (uses current app if not specified)',
required: false,
}),
}
static description = 'Delete an app'
static examples = [
'$ ably apps delete',
'$ ably apps delete app-id',
'$ ably apps delete app-id --access-token "YOUR_ACCESS_TOKEN"',
'$ ably apps delete app-id --force',
'$ ably apps delete app-id --json',
'$ ably apps delete app-id --pretty-json'
]
static flags = {
...ControlBaseCommand.globalFlags,
'force': Flags.boolean({
char: 'f',
default: false,
description: 'Skip confirmation prompt',
}),
}
async run(): Promise<void> {
const { args, flags } = await this.parse(AppsDeleteCommand)
const controlApi = this.createControlApi(flags)
// Use current app ID if none is provided
let appIdToDelete = args.id
if (!appIdToDelete) {
appIdToDelete = this.configManager.getCurrentAppId()
if (!appIdToDelete) {
const error = 'No app ID provided and no current app selected. Please provide an app ID or select a default app with "ably apps switch".'
if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonOutput({
error,
status: 'error',
success: false
}, flags));
} else {
this.error(error);
}
return;
}
}
// Check if we're deleting the current app
const isDeletingCurrentApp = appIdToDelete === this.configManager.getCurrentAppId()
try {
// Get app details
const app = await controlApi.getApp(appIdToDelete)
// If not using force flag or JSON mode, get app details and prompt for confirmation
if (!flags.force && !this.shouldOutputJson(flags)) {
this.log(`\nYou are about to delete the following app:`);
this.log(`App ID: ${app.id}`);
this.log(`Name: ${app.name}`);
this.log(`Status: ${app.status}`);
this.log(`Account ID: ${app.accountId}`);
this.log(`Created: ${this.formatDate(app.created)}`);
// For additional confirmation, prompt user to enter the app name
const nameConfirmed = await this.promptForAppName(app.name)
if (!nameConfirmed) {
if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonOutput({
appId: app.id,
error: 'Deletion cancelled - app name did not match',
status: 'cancelled',
success: false
}, flags));
} else {
this.log('Deletion cancelled - app name did not match');
}
return;
}
const confirmed = await this.promptForConfirmation(`\nAre you sure you want to delete app "${app.name}" (${app.id})? This action cannot be undone. [y/N]`)
if (!confirmed) {
if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonOutput({
appId: app.id,
error: 'Deletion cancelled by user',
status: 'cancelled',
success: false
}, flags));
} else {
this.log('Deletion cancelled');
}
return;
}
}
if (!this.shouldOutputJson(flags)) {
this.log(`Deleting app ${appIdToDelete}...`);
}
await controlApi.deleteApp(appIdToDelete)
if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonOutput({
app: {
id: app.id,
name: app.name
},
success: true,
timestamp: new Date().toISOString()
}, flags));
} else {
this.log('App deleted successfully');
}
// If we deleted the current app, run switch command to select a new one
if (isDeletingCurrentApp && !this.shouldOutputJson(flags)) {
this.log('\nThe current app was deleted. Switching to another app...');
// Create a new instance of AppsSwitch and run it
const switchCommand = new AppsSwitch(this.argv, this.config)
await switchCommand.run()
}
} catch (error) {
if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonOutput({
appId: appIdToDelete,
error: error instanceof Error ? error.message : String(error),
status: 'error',
success: false
}, flags));
} else {
this.error(`Error deleting app: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
private promptForAppName(appName: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
return new Promise<boolean>((resolve) => {
rl.question(`For confirmation, please enter the app name (${appName}): `, (answer) => {
rl.close()
resolve(answer === appName)
})
})
}
private promptForConfirmation(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
return new Promise<boolean>((resolve) => {
rl.question(message + ' ', (answer) => {
rl.close()
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')
})
})
}
}