1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | Object.defineProperty(exports, "__esModule", { value: true });
|
13 | const tslib_1 = require("tslib");
|
14 | const fuzzy_1 = tslib_1.__importDefault(require("fuzzy"));
|
15 | const base_1 = tslib_1.__importStar(require("../base"));
|
16 | const sdk_1 = require("@cto.ai/sdk");
|
17 | const CustomErrors_1 = require("../errors/CustomErrors");
|
18 | const validate_1 = require("../utils/validate");
|
19 | const utils_1 = require("../utils");
|
20 | const opConfig_1 = require("../constants/opConfig");
|
21 | const opConfig_2 = require("../constants/opConfig");
|
22 | class 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 |
|
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 | }
|
202 | exports.default = Add;
|
203 | Add.description = 'Add an op to your team.';
|
204 | Add.flags = {
|
205 | help: base_1.flags.help({ char: 'h' }),
|
206 | };
|
207 | Add.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 | ];
|