UNPKG

9.64 kBJavaScriptView Raw
1"use strict";
2/**
3 * @author: Prachi Singh (prachi@hackcapital.com)
4 * @date: Tuesday, 5th November 2019 1:11:40 pm
5 * @lastModifiedBy: Prachi Singh (prachi@hackcapital.com)
6 * @lastModifiedTime: Monday, 18th November 2019 4:28:12 pm
7 *
8 * DESCRIPTION: ops add
9 *
10 * @copyright (c) 2019 Hack Capital
11 */
12Object.defineProperty(exports, "__esModule", { value: true });
13const tslib_1 = require("tslib");
14const fuzzy_1 = tslib_1.__importDefault(require("fuzzy"));
15const base_1 = tslib_1.__importStar(require("../base"));
16const sdk_1 = require("@cto.ai/sdk");
17const CustomErrors_1 = require("../errors/CustomErrors");
18const validate_1 = require("../utils/validate");
19const utils_1 = require("../utils");
20const opConfig_1 = require("../constants/opConfig");
21const opConfig_2 = require("../constants/opConfig");
22class Add extends base_1.default {
23 constructor() {
24 super(...arguments);
25 this.ops = [];
26 this.promptFilter = async (inputs) => {
27 if (inputs.opName)
28 return inputs;
29 const answers = await sdk_1.ux.prompt({
30 type: 'input',
31 name: 'opName',
32 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')}`,
33 });
34 const opName = answers.opName;
35 return Object.assign(Object.assign({}, inputs), { opName });
36 };
37 this.isOpAlreadyInTeam = (opResults, opName, opTeamName, opVersionName, myTeamName) => {
38 if (opTeamName === myTeamName)
39 return true;
40 const result = opResults.filter(op => op.name == opName &&
41 op.teamName == opTeamName &&
42 op.version == opVersionName);
43 return Boolean(result.length);
44 };
45 this.getAllMyOps = async (config) => {
46 try {
47 const { data: opResults, } = await this.services.api.find(`private/teams/${config.team.name}/ops`, {
48 headers: {
49 Authorization: config.tokens.accessToken,
50 },
51 });
52 return opResults;
53 }
54 catch (err) {
55 this.debug('%0', err);
56 throw new CustomErrors_1.APIError(err);
57 }
58 };
59 this.getAllPublicOps = async (inputs) => {
60 if (inputs.opName)
61 return inputs;
62 try {
63 const findResponse = await this.services.api.find(`/private/ops`, {
64 headers: {
65 Authorization: inputs.config.tokens.accessToken,
66 },
67 });
68 let { data: apiOps } = findResponse;
69 apiOps = apiOps.filter(op => op.type !== opConfig_2.GLUECODE_TYPE);
70 const myOps = await this.getAllMyOps(inputs.config);
71 apiOps = apiOps.filter(op => {
72 const flag = this.isOpAlreadyInTeam(myOps, op.name, op.teamName, op.version, inputs.config.team.name);
73 return !flag;
74 });
75 this.ops = apiOps;
76 return Object.assign(Object.assign({}, inputs), { ops: apiOps });
77 }
78 catch (err) {
79 this.debug('error: %O', err);
80 throw new CustomErrors_1.APIError(err);
81 }
82 };
83 this._fuzzyFilterParams = () => {
84 const list = this.ops.map(op => {
85 const { name, teamName, version } = op;
86 const opDisplayName = this._formatOpOrWorkflowName(op);
87 const opFullName = `@${teamName}/${name}:${version}`;
88 return {
89 name: `${opDisplayName} - ${op.description || op.publishDescription}`,
90 value: opFullName,
91 };
92 });
93 const options = { extract: el => el.name };
94 return { list, options };
95 };
96 this._formatOpOrWorkflowName = (op) => {
97 const { reset, multiOrange, multiBlue } = this.ux.colors;
98 const teamName = op.teamName ? `@${op.teamName}/` : '';
99 const opVersion = op.version ? `(${op.version})` : '';
100 const name = `${reset.white(`${teamName}${op.name}`)} ${reset.dim(`${opVersion}`)}`;
101 if (op.type === opConfig_1.WORKFLOW_TYPE) {
102 return `${reset(multiOrange('\u2022'))} ${name}`;
103 }
104 else {
105 return `${reset(multiBlue('\u2022'))} ${name}`;
106 }
107 };
108 this._autocompleteSearch = async (_, input = '') => {
109 const { list, options } = this._fuzzyFilterParams();
110 const fuzzyResult = fuzzy_1.default.filter(input, list, options);
111 return fuzzyResult.map(result => result.original);
112 };
113 this.selectOpPrompt = async (inputs) => {
114 if (inputs.opName)
115 return inputs;
116 const commandText = sdk_1.ux.colors.multiBlue('\u2022Command');
117 const workflowText = sdk_1.ux.colors.multiOrange('\u2022Workflow');
118 const result = await this.ux.prompt({
119 type: 'autocomplete',
120 name: 'selectedOp',
121 pageSize: 5,
122 message: `\nSelect a public ${commandText} or ${workflowText} to add ${this.ux.colors.reset.green('ā†’')}\n${this.ux.colors.reset.dim('šŸ” Search:')} `,
123 source: this._autocompleteSearch.bind(this),
124 bottomContent: `\n \n${this.ux.colors.white(`Or, run ${this.ux.colors.callOutCyan('ops help')} for usage information.`)}`,
125 });
126 const opName = result.selectedOp;
127 return Object.assign(Object.assign({}, inputs), { opName });
128 };
129 this.checkValidOpName = async (inputs) => {
130 if (!validate_1.isValidOpFullName(inputs.opName)) {
131 this.log(`ā— Oops, that's an invalid input. Try adding the op in this format ${sdk_1.ux.colors.callOutCyan(`@teamname/opname:versionname`)}`);
132 process.exit();
133 }
134 return inputs;
135 };
136 // @teamname/opname:versionname => {teamname, opname, versionname}
137 this.splitOpName = (inputs) => {
138 const [field1, field2] = inputs.opName.split('/');
139 const opTeamName = field1.substring(1);
140 const [opName, opVersionName] = field2.split(':');
141 const opFilter = {
142 opTeamName,
143 opName,
144 opVersionName,
145 };
146 return Object.assign(Object.assign({}, inputs), { opFilter });
147 };
148 this.addOp = async (inputs) => {
149 const { opTeamName, opName, opVersionName } = inputs.opFilter;
150 if (opTeamName === inputs.config.team.name) {
151 throw new CustomErrors_1.OpAlreadyBelongsToTeam();
152 }
153 try {
154 const { data: result } = await this.services.api.create(`/private/teams/${inputs.config.team.name}/ops/refs`, { opName, opTeamName, versionName: opVersionName }, {
155 headers: {
156 Authorization: inputs.config.tokens.accessToken,
157 },
158 });
159 return Object.assign(Object.assign({}, inputs), { addedOpID: result });
160 }
161 catch (err) {
162 this.debug('%0', err);
163 if (err.error[0].message === 'op not found') {
164 throw new CustomErrors_1.OpNotFoundOpsAdd();
165 }
166 else if (err.error[0].message ===
167 'cannot create duplicate op reference for the same team') {
168 throw new CustomErrors_1.OpAlreadyAdded();
169 }
170 throw new CustomErrors_1.APIError(err);
171 }
172 };
173 this.sendAnalytics = async (inputs) => {
174 this.services.analytics.track({
175 userId: inputs.config.user.email,
176 teamId: inputs.config.team.id,
177 cliEvent: 'Ops CLI Add',
178 event: 'Ops CLI Add',
179 properties: {},
180 }, inputs.config.tokens.accessToken);
181 return inputs;
182 };
183 this.getSuccessMessage = (inputs) => {
184 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`);
185 return inputs;
186 };
187 }
188 async run() {
189 try {
190 await this.isLoggedIn();
191 const { args: { opName }, } = this.parse(Add);
192 await this.isLoggedIn();
193 const addPipeline = utils_1.asyncPipe(this.promptFilter, this.getAllPublicOps, this.selectOpPrompt, this.checkValidOpName, this.splitOpName, this.addOp, this.sendAnalytics, this.getSuccessMessage);
194 await addPipeline({ opName, config: this.state.config });
195 }
196 catch (err) {
197 this.debug('%0', err);
198 this.config.runHook('error', { err, accessToken: this.accessToken });
199 }
200 }
201}
202exports.default = Add;
203Add.description = 'Add an op to your team.';
204Add.flags = {
205 help: base_1.flags.help({ char: 'h' }),
206};
207Add.args = [
208 {
209 name: 'opName',
210 description: 'Name of the public op to be added to your team. It should be of the format - @teamname/opName:versionName',
211 },
212];