@coalescesoftware/coa 1.0.156 → 1.0.157

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.tsx +556 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coalescesoftware/coa",
3
- "version": "1.0.156",
3
+ "version": "1.0.157",
4
4
  "license": "ISC",
5
5
  "author": "Coalesce Automation, Inc.",
6
6
  "main": "index.js",
package/src/index.tsx ADDED
@@ -0,0 +1,556 @@
1
+ #! /usr/bin/env node
2
+ /* eslint-disable multiline-comment-style */
3
+
4
+ import * as Deploy from "./Deploy"
5
+ import * as Plan from "./Plan"
6
+ import * as Refresh from "./Refresh"
7
+ import * as Package from "./Package"
8
+ import * as Shared from "@coalescesoftware/shared"
9
+ import * as CLIProfile from "./CLIProfile"
10
+ import * as RunOutput from './RunOutput'
11
+ import Chalk from "chalk"
12
+ import { Command } from "commander"
13
+ import * as CommonCLI from './CommonCLI'
14
+ import fs from "fs"
15
+ import inquirer from "inquirer"
16
+
17
+ // setting this needs to be first!
18
+ Shared.Logging.SetHTTPTransportOptions(Shared.Logging.EHttpServices.CLI)
19
+ const LogCLI = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI)
20
+ const LogCLIInternal = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL)
21
+
22
+ const ChalkLogger = {
23
+ error: (message: string) => LogCLI.error(Chalk.redBright(message)),
24
+ green: (message: string) => LogCLI.info(Chalk.green(message)),
25
+ white: (message: string) => LogCLI.info(Chalk.whiteBright(message)),
26
+ blue: (message: string) => LogCLI.info(Chalk.blueBright(message)),
27
+ }
28
+
29
+ const program = new Command()
30
+ program.version(require("../package.json").version, "-v, --version")
31
+ program.option("-b, --debug", "Output extra debugging", false)
32
+ program.option("--config <coa-config-location>", "coa config file location")
33
+
34
+
35
+ const AddOverridesToCommand = (command)=> {
36
+ Object.keys(CLIProfile.ICLIProfileExample).forEach((key) => {
37
+ command.option(`--${key} <value>`, CLIProfile.ICLIProfileExample[key], "")
38
+ })
39
+ return command
40
+ }
41
+
42
+ //computeCLIOverrides returns an object that has a value if any of them have been specified at the command line
43
+ //this is used as the final override when getting a CLIConfig
44
+ const ComputeCLIOverrides = (command):Partial<CLIProfile.ICLIProfile> => {
45
+ let overrides = {}
46
+ Object.keys(CLIProfile.ICLIProfileExample).forEach((key) => {
47
+ const source = command.getOptionValueSource(key)
48
+ if (source == "cli") {
49
+ overrides[key] = command.getOptionValue(key)
50
+ }
51
+
52
+ })
53
+ return overrides
54
+ }
55
+ /**
56
+ * Default command (i.e., `coa` by itself) routes to help
57
+ */
58
+ program.command("none", { hidden: true, isDefault: true })
59
+ .action(() => {
60
+ program.help()
61
+ })
62
+
63
+
64
+ /**
65
+ * Plan command is responsible for reading files and creating a Coalesce Deployment Plan
66
+ */
67
+ AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Plan))
68
+ .option("-d, --dir <dir>", "Coalesce pipeline Yaml file path", ".")
69
+ .option("--out <plan-location>", "Coalesce plan location", "./coa-plan.json")
70
+ .description("plan a Coalesce deployment")
71
+ .action((options,cmd) => {
72
+ const cliOverrides = ComputeCLIOverrides(cmd)
73
+
74
+ const optsWithGlobals = cmd.optsWithGlobals()
75
+ const directoryPath = optsWithGlobals.dir
76
+ let logContextToUse: Shared.Logging.LogContext
77
+
78
+ // try {
79
+ // Shared.CLIOperations.VerifyAllPlanItems(config, token)
80
+ // } catch (error) {
81
+ // LogCLI.error(Chalk.redBright(`Error with required option values: ${error}`))
82
+ // Shared.CLIOperations.ExitCLISafe(1)
83
+ // }
84
+
85
+ LogCLI.info(Chalk.whiteBright(`Pipeline: ${Chalk.green("running")}...`))
86
+
87
+ const debugMode = optsWithGlobals.debug
88
+ if (!debugMode) {
89
+ Shared.CLIOperations.DisableNonCLIConsoleLogs()
90
+ }
91
+
92
+ let config;
93
+ return Promise.resolve().then(()=> {
94
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
95
+ })
96
+ .then((configResult: CLIProfile.ICLIConfig) => {
97
+ config = configResult
98
+
99
+ if (config.runtimeParameters) {
100
+ CommonCLI.ValidateRuntimeParameters(config.runtimeParameters)
101
+ }
102
+
103
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined)
104
+ })
105
+ .then(({ teamInfo, firebase }: Shared.ConnectionOperations.ITeamInfoAndFirebase) => {
106
+ const firestore = firebase.firestore()
107
+ Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID })
108
+ const teamID =teamInfo.fbTeamID
109
+ const environmentID = config.runDetails.environmentID
110
+
111
+ return Shared.SchedulerOperations.GetRuntimeParametersObjectForRun(
112
+ firestore,
113
+ teamID,
114
+ environmentID,
115
+ config.runtimeParameters)
116
+ })
117
+ .then((runtimeParametersObject:Shared.Runner.TRunTimeParametersObjectType) => {
118
+ const envID = config.runDetails.environmentID
119
+
120
+ return Plan.CreatePlan(
121
+ directoryPath,
122
+ envID,
123
+ config.token,
124
+ `Deploy to environment: ${envID}`,
125
+ JSON.stringify(runtimeParametersObject)
126
+ )
127
+ }).then(result => {
128
+ const { plan, logContext } = result
129
+ logContextToUse = logContext
130
+ fs.writeFile(optsWithGlobals.out, JSON.stringify(plan), "utf8", (error) => {
131
+ if (error) {
132
+ LogCLI.errorContext(logContextToUse, Chalk.redBright(`An error occurred while saving plan ${error}`))
133
+
134
+ return `Plan incomplete and not saved to local file.`
135
+ } else {
136
+ LogCLI.infoContext(logContextToUse, Chalk.blueBright(`Plan complete and saved to local file: coa-plan.json`))
137
+ Shared.CLIOperations.ExitCLISafe(0)
138
+ }
139
+ })
140
+ }).catch(error => {
141
+ LogCLI.errorContext(logContextToUse, Chalk.redBright(`An error occurred while creating plan ${error}`))
142
+ Shared.CLIOperations.ExitCLISafe(1)
143
+ })
144
+ })
145
+
146
+ /**
147
+ * Deploy command is responsible for taking an already generated plan, and executing it
148
+ */
149
+ AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
150
+ .option("-p, --plan <plan-location>", "Coalesce plan location", "./coa-plan.json")
151
+ .option("-o, --out <output json>", "Run Results Output in Json ")
152
+ .description("run a coalesce deployment plan")
153
+ .action((options,cmd) => {
154
+ const cliOverrides = ComputeCLIOverrides(cmd)
155
+
156
+ const optsWithGlobals = cmd.optsWithGlobals()
157
+ const plan = JSON.parse(fs.readFileSync(optsWithGlobals.plan, { encoding: "utf-8" }))
158
+ // const config = JSON.parse(fs.readFileSync(cmd.config, { encoding: "utf-8" }))
159
+ // const token = fs.readFileSync(cmd.token, { encoding: "utf-8" })
160
+
161
+ // try {
162
+ // Shared.CLIOperations.VerifyAllDeployItems(plan, config, token)
163
+ // } catch (error) {
164
+ // LogCLI.error(Chalk.redBright(`Error with required option values: ${error}`))
165
+ // Shared.CLIOperations.ExitCLISafe(1)
166
+ // }
167
+
168
+ const debugMode = optsWithGlobals.debug
169
+ if (!debugMode) {
170
+ Shared.CLIOperations.DisableNonCLIConsoleLogs()
171
+ }
172
+
173
+ let logContextToUse: Shared.Logging.LogContext
174
+ let runInfo:Shared.Runner.IRunInfo
175
+
176
+ let config;
177
+ return Promise.resolve().then(()=> {
178
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
179
+ })
180
+ .then((configResult: CLIProfile.ICLIConfig) => {
181
+ config = configResult
182
+
183
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(
184
+ config.token,
185
+ undefined,
186
+ )
187
+ }).then(({ teamInfo }: Shared.ConnectionOperations.ITeamInfoAndFirebase) => {
188
+ Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID })
189
+
190
+ runInfo = {
191
+ runType: Shared.Runner.ERunType.deploy,
192
+ runStatus: Shared.Runner.ERunStatus.running,
193
+ runDetails: {
194
+ environmentID: config.runDetails.environmentID
195
+ },
196
+ userCredentials: config.userCredentials,
197
+ runTimeParameters: plan.runtimeParameters || {},
198
+ }
199
+
200
+ Shared.Common.assert(Shared.Logging.LoggingArea.CLI,
201
+ !!runInfo, "runinfo must exist to continue")
202
+ return Deploy.DeployWithCLI(plan, runInfo, config.token)
203
+ .then((result) => {
204
+ const { runCounter, runCompletion, logContext } = result
205
+ logContextToUse = logContext ?? {}
206
+ LogCLI.infoContext(logContextToUse, Chalk.whiteBright(
207
+ `Job ${runCounter}: ${Chalk.green("running")}...`
208
+ ))
209
+
210
+ return runCompletion.finally(()=> {
211
+ const outputFilePath = optsWithGlobals.out
212
+ CommonCLI.FinishWithOutputFile(
213
+ logContextToUse,
214
+ outputFilePath,
215
+ runCounter,
216
+ config.token
217
+ )
218
+ })
219
+ })
220
+ .then(() => {
221
+ LogCLI.infoContext(logContextToUse, "Deployment successful!")
222
+ Shared.CLIOperations.ExitCLISafe(0)
223
+ })
224
+ }).catch(error => {
225
+ LogCLI.errorContext(logContextToUse, Chalk.redBright(`An error occurred during deployment ${error.toString()}`))
226
+ Shared.CLIOperations.ExitCLISafe(1)
227
+ })
228
+ })
229
+
230
+ /**
231
+ * Refresh command begins a locally executed Coalesce Environment Run
232
+ */
233
+ AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Refresh))
234
+ .description("runs a Coalesce pipeline")
235
+ .option("-o, --out <output json>", "Run Results Output in Json ")
236
+ .action(( options, command) => {
237
+ const cliOverrides = ComputeCLIOverrides(command)
238
+ const optsWithGlobals = command.optsWithGlobals()
239
+ const debugMode = optsWithGlobals.debug
240
+ if (!debugMode) {
241
+ Shared.CLIOperations.DisableNonCLIConsoleLogs()
242
+ }
243
+
244
+
245
+
246
+ let logContextToUse
247
+
248
+ //TODO:
249
+ //FROM MICHAEL:
250
+ //WHY DO WE HAVE THIS CONFIG?
251
+ let runInfo:Shared.Runner.IRunInfo
252
+ let config;
253
+ return Promise.resolve().then(()=> {
254
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
255
+ })
256
+ .then((configResult: CLIProfile.ICLIConfig) => {
257
+ config = configResult
258
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined)
259
+ })
260
+ .then(({ teamInfo, firebase }) => {
261
+ const firestore = firebase.firestore()
262
+ Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID })
263
+ const teamID = teamInfo.fbTeamID
264
+ const environmentID = config.runDetails.environmentID
265
+ return Shared.SchedulerOperations.GetRuntimeParametersObjectForRun(firestore,
266
+ teamID, environmentID, config.runtimeParameters)
267
+ })
268
+ .then((runtimeParametersObject:Shared.Runner.TRunTimeParametersObjectType) => {
269
+ runInfo = {
270
+ runType: Shared.Runner.ERunType.refresh,
271
+ runStatus: Shared.Runner.ERunStatus.running,
272
+ runDetails: {
273
+ environmentID: config.runDetails.environmentID,
274
+ jobID: config.runDetails.jobID,
275
+ includeNodesSelector: config.runDetails.includeNodesSelector,
276
+ excludeNodesSelector: config.runDetails.excludeNodesSelector
277
+ },
278
+ userCredentials:config.userCredentials,
279
+ runTimeParameters: runtimeParametersObject,
280
+ }
281
+
282
+ Shared.Common.CleanupUndefinedValuesFromObject(runInfo)
283
+
284
+ LogCLIInternal.infoContext(logContextToUse, "cliOverrides", cliOverrides)
285
+ //LogCLIInternal.infoContext(logContextToUse, "got the cli config", config)
286
+ //LogCLIInternal.infoContext(logContextToUse, "got the run info", config)
287
+ Shared.Common.assert(Shared.Logging.LoggingArea.CLI,
288
+ !!runInfo, "runinfo must exist to continue")
289
+ return Refresh.RefreshWithCLI(config.token, runInfo)
290
+ .then((result) => {
291
+ const { runCounter, runCompletion, logContext } = result
292
+ logContextToUse = logContext ?? {}
293
+ LogCLI.infoContext(logContextToUse, Chalk.whiteBright(`Refresh run initialized. RunCounter: ${runCounter}`))
294
+
295
+ return runCompletion.finally(() => {
296
+ const outputFilePath = optsWithGlobals.out
297
+ CommonCLI.FinishWithOutputFile(
298
+ logContextToUse,
299
+ outputFilePath,
300
+ runCounter,
301
+ config.token
302
+ )
303
+ }).then(() => {
304
+ LogCLI.infoContext(logContextToUse, "Refresh successful!")
305
+ Shared.CLIOperations.ExitCLISafe(0)
306
+ })
307
+ })
308
+ }).catch(error => {
309
+ LogCLI.errorContext(logContextToUse, Chalk.redBright("Error during refresh!: "), error)
310
+ Shared.CLIOperations.ExitCLISafe(1)
311
+ })
312
+ })
313
+
314
+ //////////////////////////////////////
315
+ ///// COA PACKAGES
316
+ //////////////////////////////////////
317
+
318
+ const PackageInit = program.command(Shared.CLIOperations.ECLICommands.Package)
319
+ .description("experimental feature")
320
+ // removing description until Lhotse 4.0 release
321
+ // .description(`\n--------------------------------------\n*** Experimental Feature ***\n--------------------------------------\nImport workspace information (aka Coalesce Package) from other Coalesce repositories into your the environment provided in your COA config, or --environmentID override.
322
+ // \nSubcommands:
323
+ // add <location> imports data from <location> (either URL with optional #commit, #branch, or file path)
324
+ // remove <packageID> removes imported package with <packageID> from your Coalesce project\n--------------------------------------\n`)
325
+ .option("--list [workspaceID]", "Lists installed package names for default or specified workspace")
326
+ // .command("none", { hidden: true, isDefault: true }) // removing description until Lhotse 4.0 release
327
+ .action((opts, cmd) => {
328
+ const cliOverrides = ComputeCLIOverrides(cmd)
329
+ const optsWithGlobals = cmd.optsWithGlobals()
330
+ const list = optsWithGlobals.list
331
+ const debugMode = optsWithGlobals.debug
332
+
333
+ if (!debugMode) {
334
+ Shared.CLIOperations.DisableNonCLIConsoleLogs()
335
+ }
336
+
337
+ let environmentID
338
+
339
+ if (list) {
340
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
341
+ .then((configResult: CLIProfile.ICLIConfig) => {
342
+ // if list is a boolean, then --list had no workspaceID arg, so use workspaceID from coaConfig, else use provided workspaceID
343
+ environmentID = typeof list === "boolean" ? configResult.runDetails.environmentID : list
344
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(configResult.token, undefined)
345
+ })
346
+ .then((authInfo) => {
347
+ const packageContext = Package.InitializePackageContext(authInfo, environmentID)
348
+
349
+ return Package.GetPackageListMessageCLI(packageContext)
350
+ })
351
+ .then((packageListCLI) => {
352
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(Chalk.bgBlueBright(packageListCLI))
353
+ Shared.CLIOperations.ExitCLISafe(0)
354
+ })
355
+ .catch((error) => {
356
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).error(Chalk.red(`CLI Package listing error`, error))
357
+ Shared.CLIOperations.ExitCLISafe(1)
358
+ })
359
+ } else {
360
+ program.help()
361
+ }
362
+ })
363
+
364
+ // removing description until Lhotse 4.0 release - also todo: do this better anyway
365
+ // PackageInit.command("none", { hidden: true, isDefault: true })
366
+ // .action(() => {
367
+ // PackageInit.help()
368
+ // })
369
+
370
+ const throwForbiddenExperimentalError = () => {
371
+ const errorMessage = ` 403 - Forbidden: You do not have permission to access this experimental feature`
372
+ throw new Error(errorMessage)
373
+ }
374
+
375
+ const AddPackage = AddOverridesToCommand(PackageInit.command(`${Shared.CLIOperations.ECLICommands.Add} <location>`))
376
+ // .description("imports data from <location> (either URL with optional #commit or dir path) to your Coalesce project for given environment ID") // removing description until Lhotse 4.0 release
377
+ .option("-y", "Auto-confirm all overwrite prompts")
378
+
379
+ AddPackage
380
+ .action((location, options, cmd) => {
381
+ const cliOverrides = ComputeCLIOverrides(cmd)
382
+ const optsWithGlobals = cmd.optsWithGlobals()
383
+ const debugMode = optsWithGlobals.debug
384
+ const packageLocation: string = location
385
+ const confirmPrompts: boolean = options.y || false
386
+
387
+ if (!debugMode) {
388
+ Shared.CLIOperations.DisableNonCLIConsoleLogs()
389
+ }
390
+
391
+ ChalkLogger.green(`Initializing package installation...`)
392
+
393
+ let loggerContext
394
+ let token: string
395
+ let cliConfig: CLIProfile.ICLIConfig
396
+ let environmentID
397
+ let packageContext
398
+ let packageProvider
399
+
400
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
401
+ .then((configResult: CLIProfile.ICLIConfig) => {
402
+ cliConfig = configResult
403
+ token = cliConfig.token
404
+ environmentID = cliConfig.runDetails.environmentID
405
+
406
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined)
407
+ })
408
+ .then((authInfo) => {
409
+ // this feature only available to SuperUsers until Lhotse release
410
+ if (!authInfo.teamInfo.fbHasSuperUserAccess) {
411
+ throwForbiddenExperimentalError()
412
+ }
413
+
414
+ packageContext = Package.InitializePackageContext(authInfo, environmentID)
415
+ packageProvider = new Package.PackageProvider(packageLocation, loggerContext)
416
+
417
+ // need to getWorkspaceDataFS here in order to get package ID from package provider
418
+ return packageProvider.getWorkspaceDataFS()
419
+ .then(() => Shared.Workspaces.getAllWorkspaceDataFromFirebase(authInfo.firebase.firestore(), authInfo.teamInfo.fbTeamID, environmentID))
420
+ })
421
+
422
+ .then(workspaceData => {
423
+ const isPackageAlreadyInstalled = Package.IsPackageAlreadyInstalled(workspaceData.packages || {}, packageProvider.id)
424
+
425
+ const install = () => {
426
+ return Package.InstallPackage(packageProvider, packageContext)
427
+ .then(() => {
428
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(Chalk.green(`CLI Package Installation complete`))
429
+ Shared.CLIOperations.ExitCLISafe(0)
430
+ })
431
+ }
432
+
433
+ if (isPackageAlreadyInstalled) {
434
+ if (confirmPrompts) {
435
+ return install()
436
+ } else {
437
+ const promptData = [
438
+ {
439
+ name: "confirmOverwrite",
440
+ type: "confirm",
441
+ message: `Package "${packageProvider.id}" already exists. Continuing with installation will remove any changes you might have made and overwrite the data previously imported from this package.
442
+ \n\nWould you like to continue installation and overwrite any previously installed package data from "${packageProvider.id}"?`,
443
+ default: false
444
+ },
445
+ ]
446
+
447
+ return inquirer.prompt(promptData)
448
+ .then(answers => {
449
+ const shouldOverwrite = answers.confirmOverwrite
450
+
451
+ if (shouldOverwrite) {
452
+ return install()
453
+ } else {
454
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(`CLI Package installation aborted`)
455
+ Shared.CLIOperations.ExitCLISafe(0)
456
+ }
457
+ })
458
+ }
459
+ } else {
460
+ return install()
461
+ }
462
+ })
463
+ .catch(error => {
464
+ if (error.isTtyError) {
465
+ // Prompt couldn't be rendered in the current environment
466
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`There was a problem rendering the overwrite confirmation prompt in your environment. \n\n To overwrite package without prompts, add the -y param to the end of the command and try again.`, error))
467
+ }
468
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`CLI Package Installation error`, error))
469
+ Shared.CLIOperations.ExitCLISafe(1)
470
+ })
471
+ })
472
+
473
+ const RemovePackage = AddOverridesToCommand(PackageInit.command(`${Shared.CLIOperations.ECLICommands.Remove} <id>`))
474
+ // .description("removes imported package with <id> from your Coalesce project for given environment ID") // removing description until Lhotse 4.0 release
475
+ .option("-y", "Auto-confirm all remove prompts")
476
+
477
+ RemovePackage
478
+ .action((id: string, options, cmd) => {
479
+ const cliOverrides = ComputeCLIOverrides(cmd)
480
+ const optsWithGlobals = cmd.optsWithGlobals()
481
+ const debugMode = optsWithGlobals.debug
482
+ const packageID: string = id.toUpperCase()
483
+ const confirmPrompts: boolean = options.y || false
484
+
485
+ if (!debugMode) {
486
+ Shared.CLIOperations.DisableNonCLIConsoleLogs()
487
+ }
488
+
489
+ ChalkLogger.green(`Initializing package removal...`)
490
+
491
+ let loggerContext: Shared.Logging.LogContext
492
+ let token: string
493
+ let cliConfig: CLIProfile.ICLIConfig
494
+ let environmentID: string | number
495
+
496
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
497
+ .then((configResult: CLIProfile.ICLIConfig) => {
498
+ cliConfig = configResult
499
+ token = cliConfig.token
500
+ environmentID = cliConfig.runDetails.environmentID
501
+
502
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined)
503
+ })
504
+ .then((authInfo) => {
505
+ // this feature only available to SuperUsers until Lhotse release
506
+ if (!authInfo.teamInfo.fbHasSuperUserAccess) {
507
+ throwForbiddenExperimentalError()
508
+ }
509
+
510
+ const packageContext = Package.InitializePackageContext(authInfo, environmentID as number)
511
+ const uninstall = () => Package.UninstallPackage(packageID, packageContext)
512
+ .then(() => {
513
+ ChalkLogger.green("Package removal completed successfully!")
514
+ Shared.CLIOperations.ExitCLISafe(0)
515
+ })
516
+
517
+ if (confirmPrompts) {
518
+ return uninstall()
519
+ } else {
520
+ const promptData = [
521
+ {
522
+ name: "confirmRemove",
523
+ type: "confirm",
524
+ message: `Removing a package will remove all imported data from that package, including any edits you have made on that imported data. \n\nAre you sure you'd like to remove package "${packageID}"?`,
525
+ default: false
526
+ },
527
+ ]
528
+ return inquirer.prompt(promptData)
529
+ .then(answers => {
530
+ const shouldRemove = answers.confirmRemove
531
+
532
+ if (shouldRemove) {
533
+ return uninstall()
534
+ } else {
535
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(`CLI Package removal aborted`)
536
+ Shared.CLIOperations.ExitCLISafe(0)
537
+ }
538
+ })
539
+ }
540
+ })
541
+ .catch(error => {
542
+ if (error.isTtyError) {
543
+ // Prompt couldn't be rendered in the current environment
544
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`There was a problem rendering the removal confirmation prompt in your environment. \n\n To remove without prompts, add the -y param to the end of the command and try again.`, error))
545
+ }
546
+ Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`CLI Package removal error`, error))
547
+ Shared.CLIOperations.ExitCLISafe(1)
548
+ })
549
+ })
550
+
551
+ /**
552
+ * Put new commands above.
553
+ * Don't delete the commands below; they're responsible for Commander reading and executing options.
554
+ */
555
+ program.parse()
556
+ program.opts()