UNPKG

@cto.ai/ops

Version:

šŸ’» CTO.ai - The CLI built for Teams šŸš€

275 lines (274 loc) • 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const base_1 = tslib_1.__importStar(require("../base")); const cli_sdk_1 = require("@cto.ai/cli-sdk"); const utils_1 = require("./../utils"); const env_1 = require("../constants/env"); const CustomErrors_1 = require("../errors/CustomErrors"); const ErrorTemplate_1 = require("./../errors/ErrorTemplate"); class Remove extends base_1.default { constructor() { super(...arguments); this.validateOpNameAndVersion = (inputs) => { let { op } = inputs; if (op.charAt(0) === '@' && op.includes('/')) { const [field1, field2] = op.split('/'); let opTeamName = field1 ? field1.substring(1) : inputs.config.team.name; const [opName, opVersion] = field2 ? field2.split(':') : [undefined, undefined]; if (!opName || !opVersion) { throw new CustomErrors_1.InvalidRemoveOpFormat(); } return Object.assign(Object.assign({}, inputs), { opTeamName, opName, opVersion }); } else { const [opName, opVersion] = op.split(':'); if (!opName || !opVersion) { throw new CustomErrors_1.InvalidRemoveOpFormat(); } const opTeamName = inputs.config.team.name; return Object.assign(Object.assign({}, inputs), { opTeamName, opName, opVersion }); } }; this.getApiOpsOrWorkflows = async (inputs) => { try { const { opName, opVersion, opTeamName, config: { tokens: { accessToken }, }, } = inputs; const { data: opOrWorkflow, } = await this.services.api .find(`/private/teams/${opTeamName}/ops/${opName}/versions/${opVersion}`, { headers: { Authorization: accessToken, }, }) .catch(err => { if (err.error[0].code === 404) { throw new CustomErrors_1.NoOpsFound(`${opName}:${opVersion}`, opTeamName); } throw err; }); return Object.assign(Object.assign({}, inputs), { opOrWorkflow }); } catch (err) { if (err instanceof ErrorTemplate_1.ErrorTemplate) { throw err; } this.debug('%O', err); throw new CustomErrors_1.APIError(err); } }; this.promptDeleteDescription = async (inputs) => { const { opOrWorkflow } = inputs; if (opOrWorkflow.teamName !== inputs.config.team.name) { return inputs; } const { deleteDescription } = await cli_sdk_1.ux.prompt({ type: 'input', name: 'deleteDescription', message: `\nProvide a description for why ${opOrWorkflow.name}:${opOrWorkflow.version} is being deleted ${cli_sdk_1.ux.colors.reset.green('→')}\n\n ${cli_sdk_1.ux.colors.white('āœļø Description:')}`, afterMessage: cli_sdk_1.ux.colors.reset.green('āœ“'), validate: input => { if (input === '') { return 'You need to provide a delete description of your workflow before continuing'; } if (input.length > 255) { return 'Sorry, the maximum length for a delete description is 255 characters'; } return true; }, }); return Object.assign(Object.assign({}, inputs), { deleteDescription }); }; this.promptDeleteAllDescription = async (inputs) => { const { op } = inputs; const { deleteDescription } = await cli_sdk_1.ux.prompt({ type: 'input', name: 'deleteDescription', message: `\nProvide a description for why ${op} is being deleted ${cli_sdk_1.ux.colors.reset.green('→')}\n\n ${cli_sdk_1.ux.colors.white('āœļø Description:')}`, afterMessage: cli_sdk_1.ux.colors.reset.green('āœ“'), validate: input => { if (input === '') { return 'You need to provide a delete description of your workflow before continuing'; } if (input.length > 255) { return 'Sorry, the maximum length for a delete description is 255 characters'; } return true; }, }); return Object.assign(Object.assign({}, inputs), { deleteDescription }); }; this.validateBilling = async (inputs) => { await this.services.billingService.validateBilling(inputs.config.team.name, inputs.opOrWorkflow.type, inputs.opOrWorkflow.name, inputs.config.user.email, inputs.config.user.username, inputs.config.tokens.accessToken); return Object.assign({}, inputs); }; this.confirmRemove = async (inputs) => { const { opOrWorkflow: { name, teamName, version }, } = inputs; const { confirmRemove } = await cli_sdk_1.ux.prompt({ type: 'confirm', name: 'confirmRemove', suffix: false, message: `Are you sure you want to remove @${teamName}/${name}:${version}?`, }); return Object.assign(Object.assign({}, inputs), { confirmRemove }); }; this.confirmRemoveAll = async (inputs) => { const { op, config: { team: { name: teamName }, }, } = inputs; const { confirmRemove } = await cli_sdk_1.ux.prompt({ type: 'confirm', name: 'confirmRemove', suffix: false, message: `Are you sure you want to remove all versions of @${teamName}/${op}?`, }); return Object.assign(Object.assign({}, inputs), { confirmRemove }); }; this.removeApiOpOrWorkflow = async (inputs) => { try { if (!inputs.confirmRemove) return inputs; const { opOrWorkflow: { teamName, name, version, events }, deleteDescription, config: { team: { name: ownTeamName }, tokens: { accessToken }, }, } = inputs; this.log(`\nšŸ—‘ Removing ${name}:${version}...`); if (teamName === inputs.config.team.name) { await this.services.api.remove(`/private/teams/${teamName}/ops/${name}/versions`, version, { query: { deleteDescription }, headers: { Authorization: accessToken }, }); if (Array.isArray(events)) { await this.services.subscriptionService.unsubscribeOp(name, inputs.config); } return inputs; } // remove added op await this.services.api.remove(`/private/teams/${ownTeamName}/ops/refs`, null, { query: { opTeamName: teamName, opName: name, versionName: version }, headers: { Authorization: accessToken }, }); return inputs; } catch (err) { this.debug('%O', err); this.handleNotFoundOpError(err); throw new CustomErrors_1.CannotDeleteOp(err); } }; this.removeApiOpVersions = async (inputs) => { try { if (!inputs.confirmRemove) return inputs; const { op, deleteDescription, config: { team: { name: teamName }, tokens: { accessToken }, }, } = inputs; this.log(`\nšŸ—‘ Removing all versions of ${cli_sdk_1.ux.colors.bold(`@${teamName}/${op}`)}...`); await this.services.api.remove(`/private/teams/${teamName}/ops/${op}/versions`, null, { query: { deleteDescription }, headers: { Authorization: accessToken }, }); await this.services.subscriptionService.unsubscribeOp(op, inputs.config); return inputs; } catch (err) { this.debug('%O', err); this.handleNotFoundOpError(err); throw new CustomErrors_1.CannotDeleteOp(err); } }; this.updateBilling = async (inputs) => { await this.services.billingService.updateBilling(inputs.config.team.name, inputs.config.user.username, inputs.config.user.email, inputs.config.tokens.accessToken); console.log(`${cli_sdk_1.ux.colors.tertiary('šŸ’³ Subscription has been updated...')}`); return Object.assign({}, inputs); }; this.logMessage = (inputs) => { const { opOrWorkflow: { version, name, teamName }, confirmRemove, } = inputs; if (!confirmRemove) return inputs; this.log(`\nāš”ļø ${cli_sdk_1.ux.colors.bold(`@${teamName}/${name}:${version}`)} has been successfully ${cli_sdk_1.ux.colors.green('removed')}!`); this.log(`\nTo publish again run: ${cli_sdk_1.ux.colors.green('$')} ${cli_sdk_1.ux.colors.dim('ops publish <path>')}\n`); return inputs; }; this.logRemoveAllMessage = (inputs) => { const { op, config: { team: { name: teamName }, }, confirmRemove, } = inputs; if (!confirmRemove) return inputs; this.log(`\nāš”ļø ${cli_sdk_1.ux.colors.bold(`@${teamName}/${op}`)} versions have successfully been ${cli_sdk_1.ux.colors.green('removed')}!`); this.log(`\nTo publish again run: ${cli_sdk_1.ux.colors.green('$')} ${cli_sdk_1.ux.colors.dim('ops publish <path>')}\n`); return inputs; }; this.sendAnalytics = async (inputs) => { const { opOrWorkflow, config, op } = inputs; let analyticProperties = { username: config.user.username }; if (opOrWorkflow) { const { id, name, description, version } = opOrWorkflow; analyticProperties = Object.assign(Object.assign({}, analyticProperties), { id, name, description, version, image: `${env_1.OPS_REGISTRY_HOST}/${name}:${version}` }); } else { analyticProperties = Object.assign(Object.assign({}, analyticProperties), { name: op }); } this.services.analytics.track('Ops CLI Remove', analyticProperties, config); return inputs; }; } handleNotFoundOpError(err) { if (Array.isArray(err.error)) { const [head, ...tail] = err.error; if (head.code == 404) { throw new CustomErrors_1.CannotDeleteNotFoundOp(err); } } } async run() { const { args: { workflow }, flags: { all }, } = this.parse(Remove); const config = await this.isLoggedIn(); try { let pipelineFuncs; if (all) { pipelineFuncs = [ this.confirmRemoveAll, this.promptDeleteAllDescription, this.removeApiOpVersions, // this.updateBilling, this.sendAnalytics, this.logRemoveAllMessage, ]; } else { pipelineFuncs = [ this.validateOpNameAndVersion, this.getApiOpsOrWorkflows, // this.validateBilling, this.confirmRemove, this.promptDeleteDescription, this.removeApiOpOrWorkflow, // this.updateBilling, this.sendAnalytics, this.logMessage, ]; } const removePipeline = (0, utils_1.asyncPipe)(...pipelineFuncs); await removePipeline({ op: workflow, config }); } catch (err) { this.debug('%O', err); this.config.runHook('error', { err, accessToken: config.tokens.accessToken, }); } } } exports.default = Remove; Remove.description = 'Remove a workflow from your team.'; Remove.args = [ { name: 'workflow', description: "The name and version of the workflow you want to remove. E.g. my-workflow:0.1.0\n Don't include team name or version if using the --all flag", required: true, }, ]; Remove.flags = { help: base_1.flags.help({ char: 'h' }), all: base_1.flags.boolean({ default: false, description: 'Allows you to remove all versions of a workflow on your current team.', }), };