import * as chalk from 'chalk'; import {command, flag, help, namespace, option, optional, param} from 'oo-cli'; import * as semver from 'semver'; import * as table from 'text-table'; import {die} from '../../lib/die'; import {formatVersionState} from '../../lib/formatVersionState'; import {styledStringLength} from '../../lib/StringUtils'; import {Rivendell} from '../../lib/Rivendell'; import {formatError} from '../../lib/formatError'; import AppVersion = Rivendell.AppVersion; import AppVersionState = Rivendell.AppVersionState; import DeploymentStage = Rivendell.DeploymentStage; import AppVersionSearchCriteria = Rivendell.AppVersionSearchCriteria; import ReviewStatus = Rivendell.ReviewStatus; @namespace('directory') export class ListCommand { @param @optional @help('A specific App ID to filter down to (lists all apps by default)') private appId!: string; @flag @help('Include all statuses. STOPPED and ABANDONED is filtered by default') private allStatuses: boolean = false; @option('a') @help('The availability zone that will be targeted (default: us)') private availability: string = ''; @command @help('List registered app versions') public async list(): Promise { try { const criteria: AppVersionSearchCriteria = { stages: [DeploymentStage.TEST, DeploymentStage.PRODUCTION], states: this.allStatuses ? [] : [AppVersionState.STOPPED, AppVersionState.ABANDONED], }; if (!this.allStatuses) { criteria.states = [ AppVersionState.NEW, AppVersionState.PUBLISHED, AppVersionState.BUILD_FAILED, AppVersionState.STARTING, AppVersionState.START_FAILED, AppVersionState.RUNNING, AppVersionState.UPGRADING_RUNTIME, AppVersionState.STOPPING, AppVersionState.STOP_FAILED ]; } if (this.appId) { criteria.appId = this.appId; } this.render(await Rivendell.searchAppVersions(criteria, this.availability)); } catch (e: any) { die(formatError(e)); } } private render(appVersions: AppVersion[]) { const header = ['App ID', 'Version', 'Target Product', 'State', 'Created At', 'Updated At'].map( (item) => chalk.grey(item) ); const rows = appVersions .filter((appVersion) => this.allStatuses || (appVersion.state as AppVersionState !== AppVersionState.STOPPED && appVersion.state !== AppVersionState.ABANDONED) ) .sort((lhs, rhs) => { let result = lhs.id.appId.localeCompare(rhs.id.appId); if (result === 0) { const lhsVersion = lhs.id.version; const rhsVersion = rhs.id.version; if (lhsVersion !== rhsVersion) { result = semver.gt(lhsVersion, rhsVersion) ? -1 : 1; } } return result; }) .map((appVersion) => [ appVersion.id.appId, appVersion.id.version, appVersion.accountType, this.renderState(appVersion), appVersion.createdAt, appVersion.updatedAt ]); const t = table( [ header, ...rows ], { hsep: ' '.repeat(8), stringLength: styledStringLength } ); console.log(`\n${t}\n`); } private renderState(appVersion: AppVersion): string { const state = appVersion.state as AppVersionState; const reviewStatus = appVersion.reviewStatus as Rivendell.ReviewStatus; const includeReviewStatus = reviewStatus === ReviewStatus.APPROVED || reviewStatus === ReviewStatus.IN_REVIEW; return state === AppVersionState.PUBLISHED && includeReviewStatus ? `${formatVersionState(state)} (${chalk.yellow(reviewStatus)})` : formatVersionState(state); } }