@cto.ai/ops
Version:
š» CTO.ai - The CLI built for Teams š
275 lines (274 loc) ⢠13.1 kB
JavaScript
"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.',
}),
};