UNPKG

@cto.ai/ops

Version:

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

213 lines (212 loc) • 9.63 kB
"use strict"; /** * @author: Prachi Singh (prachi@hackcapital.com) * @date: Tuesday, 5th November 2019 1:11:40 pm * @lastModifiedBy: Prachi Singh (prachi@hackcapital.com) * @lastModifiedTime: Monday, 18th November 2019 4:28:12 pm * * DESCRIPTION: ops add * * @copyright (c) 2019 Hack Capital */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const fuzzy_1 = tslib_1.__importDefault(require("fuzzy")); const base_1 = tslib_1.__importStar(require("../base")); const sdk_1 = require("@cto.ai/sdk"); const CustomErrors_1 = require("../errors/CustomErrors"); const validate_1 = require("../utils/validate"); const utils_1 = require("../utils"); const opConfig_1 = require("../constants/opConfig"); const opConfig_2 = require("../constants/opConfig"); class Add extends base_1.default { constructor() { super(...arguments); this.ops = []; this.promptFilter = async (inputs) => { if (inputs.opName) return inputs; const answers = await sdk_1.ux.prompt({ type: 'input', name: 'opName', message: `\n Please type in the name of the public op you want to add ${sdk_1.ux.colors.reset.green('→')}\n ${sdk_1.ux.colors.reset(sdk_1.ux.colors.secondary(`Leave blank to list all public ops that you can add`))} \n\n šŸ—‘ ${sdk_1.ux.colors.reset.white('Name')}`, }); const opName = answers.opName; return Object.assign(Object.assign({}, inputs), { opName }); }; this.isOpAlreadyInTeam = (opResults, opName, opTeamName, opVersionName, myTeamName) => { if (opTeamName === myTeamName) return true; const result = opResults.filter(op => op.name == opName && op.teamName == opTeamName && op.version == opVersionName); return Boolean(result.length); }; this.getAllMyOps = async (config) => { try { const { data: opResults, } = await this.services.api.find(`private/teams/${config.team.name}/ops`, { headers: { Authorization: config.tokens.accessToken, }, }); return opResults; } catch (err) { this.debug('%0', err); throw new CustomErrors_1.APIError(err); } }; this.getAllPublicOps = async (inputs) => { if (inputs.opName) return inputs; try { const findResponse = await this.services.api.find(`/private/ops`, { headers: { Authorization: inputs.config.tokens.accessToken, }, }); let { data: apiOps } = findResponse; apiOps = apiOps.filter(op => op.type !== opConfig_2.GLUECODE_TYPE); const myOps = await this.getAllMyOps(inputs.config); apiOps = apiOps.filter(op => { const flag = this.isOpAlreadyInTeam(myOps, op.name, op.teamName, op.version, inputs.config.team.name); return !flag; }); this.ops = apiOps; return Object.assign(Object.assign({}, inputs), { ops: apiOps }); } catch (err) { this.debug('error: %O', err); throw new CustomErrors_1.APIError(err); } }; this._fuzzyFilterParams = () => { const list = this.ops.map(op => { const { name, teamName, version } = op; const opDisplayName = this._formatOpOrWorkflowName(op); const opFullName = `@${teamName}/${name}:${version}`; return { name: `${opDisplayName} - ${op.description || op.publishDescription}`, value: opFullName, }; }); const options = { extract: el => el.name }; return { list, options }; }; this._formatOpOrWorkflowName = (op) => { const { reset, multiOrange, multiBlue } = this.ux.colors; const teamName = op.teamName ? `@${op.teamName}/` : ''; const opVersion = op.version ? `(${op.version})` : ''; const name = `${reset.white(`${teamName}${op.name}`)} ${reset.dim(`${opVersion}`)}`; if (op.type === opConfig_1.WORKFLOW_TYPE) { return `${reset(multiOrange('\u2022'))} ${name}`; } else { return `${reset(multiBlue('\u2022'))} ${name}`; } }; this._autocompleteSearch = async (_, input = '') => { const { list, options } = this._fuzzyFilterParams(); const fuzzyResult = fuzzy_1.default.filter(input, list, options); return fuzzyResult.map(result => result.original); }; this.selectOpPrompt = async (inputs) => { if (inputs.opName) return inputs; const commandText = sdk_1.ux.colors.multiBlue('\u2022Command'); const workflowText = sdk_1.ux.colors.multiOrange('\u2022Workflow'); const result = await this.ux.prompt({ type: 'autocomplete', name: 'selectedOp', pageSize: 5, message: `\nSelect a public ${commandText} or ${workflowText} to add ${this.ux.colors.reset.green('→')}\n${this.ux.colors.reset.dim('šŸ” Search:')} `, source: this._autocompleteSearch.bind(this), bottomContent: `\n \n${this.ux.colors.white(`Or, run ${this.ux.colors.callOutCyan('ops help')} for usage information.`)}`, }); const opName = result.selectedOp; return Object.assign(Object.assign({}, inputs), { opName }); }; this.checkValidOpName = async (inputs) => { if (!validate_1.isValidOpFullName(inputs.opName)) { this.log(`ā— Oops, that's an invalid input. Try adding the op in this format ${sdk_1.ux.colors.callOutCyan(`@teamname/opname:versionname`)}`); process.exit(); } return inputs; }; // @teamname/opname:versionname => {teamname, opname, versionname} this.splitOpName = (inputs) => { const [field1, field2] = inputs.opName.split('/'); const opTeamName = field1.substring(1); const [opName, opVersionName] = field2.split(':'); const opFilter = { opTeamName, opName, opVersionName, }; return Object.assign(Object.assign({}, inputs), { opFilter }); }; this.addOp = async (inputs) => { const { opTeamName, opName, opVersionName } = inputs.opFilter; if (opTeamName === inputs.config.team.name) { throw new CustomErrors_1.OpAlreadyBelongsToTeam(); } try { const { data: result } = await this.services.api.create(`/private/teams/${inputs.config.team.name}/ops/refs`, { opName, opTeamName, versionName: opVersionName }, { headers: { Authorization: inputs.config.tokens.accessToken, }, }); return Object.assign(Object.assign({}, inputs), { addedOpID: result }); } catch (err) { this.debug('%0', err); if (err.error[0].message === 'op not found') { throw new CustomErrors_1.OpNotFoundOpsAdd(); } else if (err.error[0].message === 'cannot create duplicate op reference for the same team') { throw new CustomErrors_1.OpAlreadyAdded(); } throw new CustomErrors_1.APIError(err); } }; this.sendAnalytics = async (inputs) => { this.services.analytics.track({ userId: inputs.config.user.id, teamId: inputs.config.team.id, cliEvent: 'Ops CLI Add', event: 'Ops CLI Add', properties: {}, }, inputs.config.tokens.accessToken); return inputs; }; this.getSuccessMessage = (inputs) => { this.log(`\nšŸŽ‰ Good job! ${sdk_1.ux.colors.callOutCyan(`${inputs.opName}`)} has been successfully added to your team. \n\n Type ${this.ux.colors.italic.dim('ops list')} to find this op in your list of ops.\n`); return inputs; }; } async run() { try { await this.isLoggedIn(); const { args: { opName }, } = this.parse(Add); await this.isLoggedIn(); const addPipeline = utils_1.asyncPipe(this.promptFilter, this.getAllPublicOps, this.selectOpPrompt, this.checkValidOpName, this.splitOpName, this.addOp, this.sendAnalytics, this.getSuccessMessage); await addPipeline({ opName, config: this.state.config }); } catch (err) { this.debug('%0', err); this.config.runHook('error', { err, accessToken: this.accessToken }); } } } exports.default = Add; Add.description = 'Add an op to your team.'; Add.flags = { help: base_1.flags.help({ char: 'h' }), }; Add.args = [ { name: 'opName', description: 'Name of the public op to be added to your team. It should be of the format - @teamname/opName:versionName', }, ];