react-native-update-cli 2.7.1 → 2.7.2

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.
Files changed (44) hide show
  1. package/cli.json +1 -0
  2. package/lib/esm/api..mjs +183 -0
  3. package/lib/esm/app..mjs +130 -0
  4. package/lib/esm/bundle..mjs +823 -0
  5. package/lib/esm/exports..mjs +11 -0
  6. package/lib/esm/index..mjs +122 -0
  7. package/lib/esm/install..mjs +18 -0
  8. package/lib/esm/locales/en..mjs +131 -0
  9. package/lib/esm/locales/zh..mjs +130 -0
  10. package/lib/esm/module-manager..mjs +109 -0
  11. package/lib/esm/modules/app-module..mjs +213 -0
  12. package/lib/esm/modules/bundle-module..mjs +178 -0
  13. package/lib/esm/modules/index..mjs +17 -0
  14. package/lib/esm/modules/package-module..mjs +6 -0
  15. package/lib/esm/modules/user-module..mjs +351 -0
  16. package/lib/esm/modules/version-module..mjs +6 -0
  17. package/lib/esm/package..mjs +316 -0
  18. package/lib/esm/provider..mjs +293 -0
  19. package/lib/esm/types..mjs +1 -0
  20. package/lib/esm/user..mjs +36 -0
  21. package/lib/esm/utils/add-gitignore..mjs +32 -0
  22. package/lib/esm/utils/app-info-parser/aab..mjs +215 -0
  23. package/lib/esm/utils/app-info-parser/apk..mjs +75 -0
  24. package/lib/esm/utils/app-info-parser/app..mjs +3 -0
  25. package/lib/esm/utils/app-info-parser/index..mjs +44 -0
  26. package/lib/esm/utils/app-info-parser/ipa..mjs +73 -0
  27. package/lib/esm/utils/app-info-parser/resource-finder..mjs +401 -0
  28. package/lib/esm/utils/app-info-parser/utils..mjs +121 -0
  29. package/lib/esm/utils/app-info-parser/xml-parser/binary..mjs +569 -0
  30. package/lib/esm/utils/app-info-parser/xml-parser/manifest..mjs +200 -0
  31. package/lib/esm/utils/app-info-parser/zip..mjs +65 -0
  32. package/lib/esm/utils/check-lockfile..mjs +78 -0
  33. package/lib/esm/utils/check-plugin..mjs +25 -0
  34. package/lib/esm/utils/constants..mjs +19 -0
  35. package/lib/esm/utils/dep-versions..mjs +33 -0
  36. package/lib/esm/utils/git..mjs +43 -0
  37. package/lib/esm/utils/http-helper..mjs +70 -0
  38. package/lib/esm/utils/i18n..mjs +23 -0
  39. package/lib/esm/utils/index..mjs +316 -0
  40. package/lib/esm/utils/latest-version/cli..mjs +294 -0
  41. package/lib/esm/utils/latest-version/index..mjs +238 -0
  42. package/lib/esm/utils/plugin-config..mjs +23 -0
  43. package/lib/esm/versions..mjs +290 -0
  44. package/package.json +19 -2
@@ -0,0 +1,351 @@
1
+ import { getSession, loadSession } from "../api";
2
+ import { userCommands } from "../user";
3
+ export const userModule = {
4
+ name: 'user',
5
+ version: '1.0.0',
6
+ commands: [],
7
+ workflows: [
8
+ {
9
+ name: 'auth-check',
10
+ description: 'Check authentication status and user information',
11
+ options: {
12
+ autoLogin: {
13
+ default: false,
14
+ description: 'Automatically login if not authenticated'
15
+ },
16
+ showDetails: {
17
+ default: true,
18
+ description: 'Show detailed user information'
19
+ }
20
+ },
21
+ steps: [
22
+ {
23
+ name: 'load-session',
24
+ description: 'Load existing session from local storage',
25
+ execute: async (context)=>{
26
+ console.log('Loading session from local storage...');
27
+ try {
28
+ await loadSession();
29
+ const session = getSession();
30
+ if (session && session.token) {
31
+ console.log('✓ Session found in local storage');
32
+ return {
33
+ sessionLoaded: true,
34
+ hasToken: true,
35
+ session
36
+ };
37
+ } else {
38
+ console.log('✗ No valid session found in local storage');
39
+ return {
40
+ sessionLoaded: true,
41
+ hasToken: false,
42
+ session: null
43
+ };
44
+ }
45
+ } catch (error) {
46
+ console.log('✗ Failed to load session:', error instanceof Error ? error.message : 'Unknown error');
47
+ return {
48
+ sessionLoaded: false,
49
+ hasToken: false,
50
+ session: null,
51
+ error: error instanceof Error ? error.message : 'Unknown error'
52
+ };
53
+ }
54
+ }
55
+ },
56
+ {
57
+ name: 'validate-session',
58
+ description: 'Validate session by calling API',
59
+ execute: async (context, previousResult)=>{
60
+ if (!previousResult.hasToken) {
61
+ console.log('No token available, skipping validation');
62
+ return {
63
+ ...previousResult,
64
+ validated: false,
65
+ reason: 'No token available'
66
+ };
67
+ }
68
+ console.log('Validating session with server...');
69
+ try {
70
+ await userCommands.me();
71
+ console.log('✓ Session is valid');
72
+ return {
73
+ ...previousResult,
74
+ validated: true,
75
+ reason: 'Session validated successfully'
76
+ };
77
+ } catch (error) {
78
+ console.log('✗ Session validation failed:', error instanceof Error ? error.message : 'Unknown error');
79
+ return {
80
+ ...previousResult,
81
+ validated: false,
82
+ reason: error instanceof Error ? error.message : 'Unknown error'
83
+ };
84
+ }
85
+ }
86
+ },
87
+ {
88
+ name: 'get-user-info',
89
+ description: 'Get current user information',
90
+ execute: async (context, previousResult)=>{
91
+ if (!previousResult.validated) {
92
+ console.log('Session not valid, cannot get user info');
93
+ return {
94
+ ...previousResult,
95
+ userInfo: null,
96
+ reason: 'Session not valid'
97
+ };
98
+ }
99
+ console.log('Getting user information...');
100
+ try {
101
+ const { get } = await import("../api");
102
+ const userInfo = await get('/user/me');
103
+ console.log('✓ User information retrieved successfully');
104
+ if (context.options.showDetails !== false) {
105
+ console.log('\n=== User Information ===');
106
+ for (const [key, value] of Object.entries(userInfo)){
107
+ if (key !== 'ok') {
108
+ console.log(`${key}: ${value}`);
109
+ }
110
+ }
111
+ console.log('========================\n');
112
+ }
113
+ return {
114
+ ...previousResult,
115
+ userInfo,
116
+ reason: 'User info retrieved successfully'
117
+ };
118
+ } catch (error) {
119
+ console.log('✗ Failed to get user info:', error instanceof Error ? error.message : 'Unknown error');
120
+ return {
121
+ ...previousResult,
122
+ userInfo: null,
123
+ reason: error instanceof Error ? error.message : 'Unknown error'
124
+ };
125
+ }
126
+ }
127
+ },
128
+ {
129
+ name: 'handle-auth-failure',
130
+ description: 'Handle authentication failure',
131
+ execute: async (context, previousResult)=>{
132
+ if (previousResult.validated) {
133
+ console.log('✓ Authentication check completed successfully');
134
+ return {
135
+ ...previousResult,
136
+ authCheckComplete: true,
137
+ status: 'authenticated'
138
+ };
139
+ }
140
+ console.log('✗ Authentication check failed');
141
+ if (context.options.autoLogin) {
142
+ console.log('Attempting automatic login...');
143
+ try {
144
+ await userCommands.login({
145
+ args: []
146
+ });
147
+ console.log('✓ Automatic login successful');
148
+ return {
149
+ ...previousResult,
150
+ authCheckComplete: true,
151
+ status: 'auto-logged-in',
152
+ autoLoginSuccess: true
153
+ };
154
+ } catch (error) {
155
+ console.log('✗ Automatic login failed:', error instanceof Error ? error.message : 'Unknown error');
156
+ return {
157
+ ...previousResult,
158
+ authCheckComplete: true,
159
+ status: 'failed',
160
+ autoLoginSuccess: false,
161
+ autoLoginError: error instanceof Error ? error.message : 'Unknown error'
162
+ };
163
+ }
164
+ } else {
165
+ console.log('Please run login command to authenticate');
166
+ return {
167
+ ...previousResult,
168
+ authCheckComplete: true,
169
+ status: 'unauthenticated',
170
+ suggestion: 'Run login command to authenticate'
171
+ };
172
+ }
173
+ }
174
+ }
175
+ ]
176
+ },
177
+ {
178
+ name: 'login-flow',
179
+ description: 'Complete login flow with validation',
180
+ options: {
181
+ email: {
182
+ hasValue: true,
183
+ description: 'User email'
184
+ },
185
+ password: {
186
+ hasValue: true,
187
+ description: 'User password'
188
+ },
189
+ validateAfterLogin: {
190
+ default: true,
191
+ description: 'Validate session after login'
192
+ }
193
+ },
194
+ steps: [
195
+ {
196
+ name: 'check-existing-session',
197
+ description: 'Check if user is already logged in',
198
+ execute: async (context)=>{
199
+ console.log('Checking existing session...');
200
+ try {
201
+ await loadSession();
202
+ const session = getSession();
203
+ if (session && session.token) {
204
+ try {
205
+ await userCommands.me();
206
+ console.log('✓ User is already logged in');
207
+ return {
208
+ alreadyLoggedIn: true,
209
+ session: session,
210
+ status: 'authenticated'
211
+ };
212
+ } catch (error) {
213
+ console.log('✗ Existing session is invalid, proceeding with login');
214
+ return {
215
+ alreadyLoggedIn: false,
216
+ session: null,
217
+ status: 'session-expired'
218
+ };
219
+ }
220
+ } else {
221
+ console.log('No existing session found');
222
+ return {
223
+ alreadyLoggedIn: false,
224
+ session: null,
225
+ status: 'no-session'
226
+ };
227
+ }
228
+ } catch (error) {
229
+ console.log('Error checking existing session:', error instanceof Error ? error.message : 'Unknown error');
230
+ return {
231
+ alreadyLoggedIn: false,
232
+ session: null,
233
+ status: 'error',
234
+ error: error instanceof Error ? error.message : 'Unknown error'
235
+ };
236
+ }
237
+ }
238
+ },
239
+ {
240
+ name: 'perform-login',
241
+ description: 'Perform user login',
242
+ execute: async (context, previousResult)=>{
243
+ if (previousResult.alreadyLoggedIn) {
244
+ console.log('Skipping login - user already authenticated');
245
+ return {
246
+ ...previousResult,
247
+ loginPerformed: false,
248
+ loginSuccess: true
249
+ };
250
+ }
251
+ console.log('Performing login...');
252
+ try {
253
+ const loginArgs = [];
254
+ if (context.options.email) {
255
+ loginArgs.push(context.options.email);
256
+ }
257
+ if (context.options.password) {
258
+ loginArgs.push(context.options.password);
259
+ }
260
+ await userCommands.login({
261
+ args: loginArgs
262
+ });
263
+ console.log('✓ Login successful');
264
+ return {
265
+ ...previousResult,
266
+ loginPerformed: true,
267
+ loginSuccess: true
268
+ };
269
+ } catch (error) {
270
+ console.log('✗ Login failed:', error instanceof Error ? error.message : 'Unknown error');
271
+ return {
272
+ ...previousResult,
273
+ loginPerformed: true,
274
+ loginSuccess: false,
275
+ loginError: error instanceof Error ? error.message : 'Unknown error'
276
+ };
277
+ }
278
+ }
279
+ },
280
+ {
281
+ name: 'validate-login',
282
+ description: 'Validate login by getting user info',
283
+ execute: async (context, previousResult)=>{
284
+ if (!previousResult.loginSuccess && !previousResult.alreadyLoggedIn) {
285
+ console.log('Login failed, skipping validation');
286
+ return {
287
+ ...previousResult,
288
+ validationPerformed: false,
289
+ validationSuccess: false
290
+ };
291
+ }
292
+ if (context.options.validateAfterLogin === false) {
293
+ console.log('Skipping validation as requested');
294
+ return {
295
+ ...previousResult,
296
+ validationPerformed: false,
297
+ validationSuccess: true
298
+ };
299
+ }
300
+ console.log('Validating login by getting user information...');
301
+ try {
302
+ const userInfo = await userCommands.me();
303
+ console.log('✓ Login validation successful');
304
+ return {
305
+ ...previousResult,
306
+ validationPerformed: true,
307
+ validationSuccess: true,
308
+ userInfo
309
+ };
310
+ } catch (error) {
311
+ console.log('✗ Login validation failed:', error instanceof Error ? error.message : 'Unknown error');
312
+ return {
313
+ ...previousResult,
314
+ validationPerformed: true,
315
+ validationSuccess: false,
316
+ validationError: error instanceof Error ? error.message : 'Unknown error'
317
+ };
318
+ }
319
+ }
320
+ },
321
+ {
322
+ name: 'login-summary',
323
+ description: 'Provide login flow summary',
324
+ execute: async (context, previousResult)=>{
325
+ console.log('\n=== Login Flow Summary ===');
326
+ if (previousResult.alreadyLoggedIn) {
327
+ console.log('Status: Already logged in');
328
+ console.log('Session: Valid');
329
+ } else if (previousResult.loginSuccess) {
330
+ console.log('Status: Login successful');
331
+ if (previousResult.validationSuccess) {
332
+ console.log('Validation: Passed');
333
+ } else {
334
+ console.log('Validation: Failed');
335
+ }
336
+ } else {
337
+ console.log('Status: Login failed');
338
+ console.log('Error:', previousResult.loginError || 'Unknown error');
339
+ }
340
+ console.log('==========================\n');
341
+ return {
342
+ ...previousResult,
343
+ flowComplete: true,
344
+ finalStatus: previousResult.alreadyLoggedIn || previousResult.loginSuccess ? 'success' : 'failed'
345
+ };
346
+ }
347
+ }
348
+ ]
349
+ }
350
+ ]
351
+ };
@@ -0,0 +1,6 @@
1
+ export const versionModule = {
2
+ name: 'version',
3
+ version: '1.0.0',
4
+ commands: [],
5
+ workflows: []
6
+ };
@@ -0,0 +1,316 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ import fs from "fs-extra";
4
+ import Table from "tty-table";
5
+ import { doDelete, getAllPackages, post, uploadFile } from "./api";
6
+ import { getPlatform, getSelectedApp } from "./app";
7
+ import { getAabInfo, getApkInfo, getAppInfo, getIpaInfo, question, saveToLocal } from "./utils";
8
+ import { AabParser } from "./utils/app-info-parser/aab";
9
+ import { depVersions } from "./utils/dep-versions";
10
+ import { getCommitInfo } from "./utils/git";
11
+ import { t } from "./utils/i18n";
12
+ export async function listPackage(appId) {
13
+ const allPkgs = await getAllPackages(appId) || [];
14
+ const header = [
15
+ {
16
+ value: t('nativePackageId')
17
+ },
18
+ {
19
+ value: t('nativeVersion')
20
+ }
21
+ ];
22
+ const rows = [];
23
+ for (const pkg of allPkgs){
24
+ const { version } = pkg;
25
+ let versionInfo = '';
26
+ if (version) {
27
+ const versionObj = version;
28
+ versionInfo = t('boundTo', {
29
+ name: versionObj.name || version,
30
+ id: versionObj.id || version
31
+ });
32
+ }
33
+ let output = pkg.name;
34
+ if (pkg.status === 'paused') {
35
+ output += t('pausedStatus');
36
+ }
37
+ if (pkg.status === 'expired') {
38
+ output += t('expiredStatus');
39
+ }
40
+ output += versionInfo;
41
+ rows.push([
42
+ pkg.id,
43
+ output
44
+ ]);
45
+ }
46
+ console.log(Table(header, rows).render());
47
+ console.log(t('totalPackages', {
48
+ count: allPkgs.length
49
+ }));
50
+ return allPkgs;
51
+ }
52
+ export async function choosePackage(appId) {
53
+ const list = await listPackage(appId);
54
+ while(true){
55
+ const id = await question(t('enterNativePackageId'));
56
+ const app = list == null ? void 0 : list.find((v)=>v.id.toString() === id);
57
+ if (app) {
58
+ return app;
59
+ }
60
+ }
61
+ }
62
+ export const packageCommands = {
63
+ uploadIpa: async ({ args, options })=>{
64
+ const fn = args[0];
65
+ if (!fn || !fn.endsWith('.ipa')) {
66
+ throw new Error(t('usageUploadIpa'));
67
+ }
68
+ const ipaInfo = await getIpaInfo(fn);
69
+ const { versionName: extractedVersionName, buildTime } = ipaInfo;
70
+ const appIdInPkg = ipaInfo.appId;
71
+ const appKeyInPkg = ipaInfo.appKey;
72
+ const { appId, appKey } = await getSelectedApp('ios');
73
+ if (appIdInPkg && appIdInPkg != appId) {
74
+ throw new Error(t('appIdMismatchIpa', {
75
+ appIdInPkg,
76
+ appId
77
+ }));
78
+ }
79
+ if (appKeyInPkg && appKeyInPkg !== appKey) {
80
+ throw new Error(t('appKeyMismatchIpa', {
81
+ appKeyInPkg,
82
+ appKey
83
+ }));
84
+ }
85
+ // Use custom version if provided, otherwise use extracted version
86
+ const versionName = options.version || extractedVersionName;
87
+ if (options.version) {
88
+ console.log(t('usingCustomVersion', {
89
+ version: versionName
90
+ }));
91
+ }
92
+ const { hash } = await uploadFile(fn);
93
+ const { id } = await post(`/app/${appId}/package/create`, {
94
+ name: versionName,
95
+ hash,
96
+ buildTime,
97
+ deps: depVersions,
98
+ commit: await getCommitInfo()
99
+ });
100
+ saveToLocal(fn, `${appId}/package/${id}.ipa`);
101
+ console.log(t('ipaUploadSuccess', {
102
+ id,
103
+ version: versionName,
104
+ buildTime
105
+ }));
106
+ },
107
+ uploadApk: async ({ args, options })=>{
108
+ const fn = args[0];
109
+ if (!fn || !fn.endsWith('.apk')) {
110
+ throw new Error(t('usageUploadApk'));
111
+ }
112
+ const apkInfo = await getApkInfo(fn);
113
+ const { versionName: extractedVersionName, buildTime } = apkInfo;
114
+ const appIdInPkg = apkInfo.appId;
115
+ const appKeyInPkg = apkInfo.appKey;
116
+ const { appId, appKey } = await getSelectedApp('android');
117
+ if (appIdInPkg && appIdInPkg != appId) {
118
+ throw new Error(t('appIdMismatchApk', {
119
+ appIdInPkg,
120
+ appId
121
+ }));
122
+ }
123
+ if (appKeyInPkg && appKeyInPkg !== appKey) {
124
+ throw new Error(t('appKeyMismatchApk', {
125
+ appKeyInPkg,
126
+ appKey
127
+ }));
128
+ }
129
+ // Use custom version if provided, otherwise use extracted version
130
+ const versionName = options.version || extractedVersionName;
131
+ if (options.version) {
132
+ console.log(t('usingCustomVersion', {
133
+ version: versionName
134
+ }));
135
+ }
136
+ const { hash } = await uploadFile(fn);
137
+ const { id } = await post(`/app/${appId}/package/create`, {
138
+ name: versionName,
139
+ hash,
140
+ buildTime,
141
+ deps: depVersions,
142
+ commit: await getCommitInfo()
143
+ });
144
+ saveToLocal(fn, `${appId}/package/${id}.apk`);
145
+ console.log(t('apkUploadSuccess', {
146
+ id,
147
+ version: versionName,
148
+ buildTime
149
+ }));
150
+ },
151
+ uploadAab: async ({ args, options })=>{
152
+ const source = args[0];
153
+ if (!source || !source.endsWith('.aab')) {
154
+ throw new Error(t('usageUploadAab'));
155
+ }
156
+ const output = path.join(os.tmpdir(), `${path.basename(source, path.extname(source))}-${Date.now()}.apk`);
157
+ const includeAllSplits = options.includeAllSplits === true || options.includeAllSplits === 'true';
158
+ const splits = options.splits ? String(options.splits).split(',').map((item)=>item.trim()).filter(Boolean) : null;
159
+ const parser = new AabParser(source);
160
+ try {
161
+ await parser.extractApk(output, {
162
+ includeAllSplits,
163
+ splits
164
+ });
165
+ await packageCommands.uploadApk({
166
+ args: [
167
+ output
168
+ ],
169
+ options
170
+ });
171
+ } finally{
172
+ if (await fs.pathExists(output)) {
173
+ await fs.remove(output);
174
+ }
175
+ }
176
+ },
177
+ uploadApp: async ({ args, options })=>{
178
+ const fn = args[0];
179
+ if (!fn || !fn.endsWith('.app')) {
180
+ throw new Error(t('usageUploadApp'));
181
+ }
182
+ const appInfo = await getAppInfo(fn);
183
+ const { versionName: extractedVersionName, buildTime } = appInfo;
184
+ const appIdInPkg = appInfo.appId;
185
+ const appKeyInPkg = appInfo.appKey;
186
+ const { appId, appKey } = await getSelectedApp('harmony');
187
+ if (appIdInPkg && appIdInPkg != appId) {
188
+ throw new Error(t('appIdMismatchApp', {
189
+ appIdInPkg,
190
+ appId
191
+ }));
192
+ }
193
+ if (appKeyInPkg && appKeyInPkg !== appKey) {
194
+ throw new Error(t('appKeyMismatchApp', {
195
+ appKeyInPkg,
196
+ appKey
197
+ }));
198
+ }
199
+ // Use custom version if provided, otherwise use extracted version
200
+ const versionName = options.version || extractedVersionName;
201
+ if (options.version) {
202
+ console.log(t('usingCustomVersion', {
203
+ version: versionName
204
+ }));
205
+ }
206
+ const { hash } = await uploadFile(fn);
207
+ const { id } = await post(`/app/${appId}/package/create`, {
208
+ name: versionName,
209
+ hash,
210
+ buildTime: String(buildTime),
211
+ deps: depVersions,
212
+ commit: await getCommitInfo()
213
+ });
214
+ saveToLocal(fn, `${appId}/package/${id}.app`);
215
+ console.log(t('appUploadSuccess', {
216
+ id,
217
+ version: versionName,
218
+ buildTime
219
+ }));
220
+ },
221
+ parseApp: async ({ args })=>{
222
+ const fn = args[0];
223
+ if (!fn || !fn.endsWith('.app')) {
224
+ throw new Error(t('usageParseApp'));
225
+ }
226
+ console.log(await getAppInfo(fn));
227
+ },
228
+ parseIpa: async ({ args })=>{
229
+ const fn = args[0];
230
+ if (!fn || !fn.endsWith('.ipa')) {
231
+ throw new Error(t('usageParseIpa'));
232
+ }
233
+ console.log(await getIpaInfo(fn));
234
+ },
235
+ parseApk: async ({ args })=>{
236
+ const fn = args[0];
237
+ if (!fn || !fn.endsWith('.apk')) {
238
+ throw new Error(t('usageParseApk'));
239
+ }
240
+ console.log(await getApkInfo(fn));
241
+ },
242
+ parseAab: async ({ args })=>{
243
+ const fn = args[0];
244
+ if (!fn || !fn.endsWith('.aab')) {
245
+ throw new Error(t('usageParseAab'));
246
+ }
247
+ console.log(await getAabInfo(fn));
248
+ },
249
+ extractApk: async ({ args, options })=>{
250
+ const source = args[0];
251
+ if (!source || !source.endsWith('.aab')) {
252
+ throw new Error(t('usageExtractApk'));
253
+ }
254
+ const output = options.output || path.join(path.dirname(source), `${path.basename(source, path.extname(source))}.apk`);
255
+ const includeAllSplits = options.includeAllSplits === true || options.includeAllSplits === 'true';
256
+ const splits = options.splits ? String(options.splits).split(',').map((item)=>item.trim()).filter(Boolean) : null;
257
+ const parser = new AabParser(source);
258
+ await parser.extractApk(output, {
259
+ includeAllSplits,
260
+ splits
261
+ });
262
+ console.log(t('apkExtracted', {
263
+ output
264
+ }));
265
+ },
266
+ packages: async ({ options })=>{
267
+ const platform = await getPlatform(options.platform);
268
+ const { appId } = await getSelectedApp(platform);
269
+ await listPackage(appId);
270
+ },
271
+ deletePackage: async ({ args, options })=>{
272
+ let { appId, packageId, packageVersion } = options;
273
+ if (!appId) {
274
+ const platform = await getPlatform(options.platform);
275
+ appId = (await getSelectedApp(platform)).appId;
276
+ }
277
+ // If no packageId provided as argument, let user choose from list
278
+ if (!packageId) {
279
+ const allPkgs = await getAllPackages(appId);
280
+ if (!allPkgs) {
281
+ throw new Error(t('noPackagesFound', {
282
+ appId
283
+ }));
284
+ }
285
+ const selectedPackage = allPkgs.find((pkg)=>pkg.name === packageVersion);
286
+ if (!selectedPackage) {
287
+ throw new Error(t('packageNotFound', {
288
+ packageVersion
289
+ }));
290
+ }
291
+ packageId = selectedPackage.id;
292
+ }
293
+ // Confirm deletion
294
+ // const confirmDelete = await question(
295
+ // t('confirmDeletePackage', { packageId }),
296
+ // );
297
+ // if (
298
+ // confirmDelete.toLowerCase() !== 'y' &&
299
+ // confirmDelete.toLowerCase() !== 'yes'
300
+ // ) {
301
+ // console.log(t('cancelled'));
302
+ // return;
303
+ // }
304
+ try {
305
+ await doDelete(`/app/${appId}/package/${packageId}`);
306
+ console.log(t('deletePackageSuccess', {
307
+ packageId
308
+ }));
309
+ } catch (error) {
310
+ throw new Error(t('deletePackageError', {
311
+ packageId,
312
+ error: error.message
313
+ }));
314
+ }
315
+ }
316
+ };