UNPKG

8.66 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const fuzzy_1 = tslib_1.__importDefault(require("fuzzy"));
5const fs = tslib_1.__importStar(require("fs-extra"));
6const path = tslib_1.__importStar(require("path"));
7const base_1 = tslib_1.__importStar(require("../base"));
8const asyncPipe_1 = require("../utils/asyncPipe");
9const CustomErrors_1 = require("../errors/CustomErrors");
10const opConfig_1 = require("../constants/opConfig");
11const utils_1 = require("../utils");
12class Search extends base_1.default {
13 constructor() {
14 super(...arguments);
15 this.opsAndWorkflows = [];
16 this.getApiOps = async (inputs) => {
17 try {
18 const findResponse = await this.services.api.find(`/private/ops`, {
19 headers: {
20 Authorization: this.accessToken,
21 },
22 });
23 let { data: apiOps } = findResponse;
24 apiOps = apiOps.filter(op => op.type !== opConfig_1.GLUECODE_TYPE);
25 return Object.assign(Object.assign({}, inputs), { apiOps });
26 }
27 catch (err) {
28 this.debug('error: %O', err);
29 throw new CustomErrors_1.APIError(err);
30 }
31 };
32 this.getLocalWorkflows = async (inputs) => {
33 const localWorkflows = [];
34 try {
35 const manifest = await fs.readFile(path.join(process.cwd(), opConfig_1.OP_FILE), 'utf8');
36 if (!manifest)
37 return inputs;
38 const { workflows = [] } = utils_1.parseYaml(manifest);
39 workflows.forEach(workflow => (workflow.local = true));
40 return Object.assign(Object.assign({}, inputs), { localWorkflows: workflows });
41 }
42 catch (_a) {
43 return Object.assign(Object.assign({}, inputs), { localWorkflows });
44 }
45 };
46 this._removeIfNameOrDescriptionDontContainQuery = (filter) => (workflow) => {
47 return (workflow.name.includes(filter) || workflow.description.includes(filter));
48 };
49 this.filterLocalWorkflows = (inputs) => {
50 let { localWorkflows, filter } = inputs;
51 if (!localWorkflows.length)
52 return inputs;
53 localWorkflows = localWorkflows.filter(this._removeIfNameOrDescriptionDontContainQuery(filter));
54 return Object.assign(Object.assign({}, inputs), { localWorkflows });
55 };
56 this._removeIfLocalExists = (workflows) => (apiOp) => {
57 const match = workflows.find(workflow => workflow.name === apiOp.name);
58 return !match;
59 };
60 this.resolveLocalAndApi = (inputs) => {
61 const { apiOps, localWorkflows } = inputs;
62 const ops = apiOps.filter(this._removeIfLocalExists(localWorkflows));
63 this.opsAndWorkflows = [...ops, ...localWorkflows].sort((a, b) => {
64 if (a.name < b.name)
65 return -1;
66 if (b.name < a.name)
67 return 1;
68 return 0;
69 });
70 return inputs;
71 };
72 this.checkData = async (inputs) => {
73 if (!this.opsAndWorkflows.length) {
74 this.log(`\n šŸ˜ž No ops found in your team, public or local workspaces. Try again or run ${this.ux.colors.callOutCyan('ops publish')} to create an op. \n`);
75 }
76 return inputs;
77 };
78 this.selectOpOrWorkflowPrompt = async (inputs) => {
79 const commandText = this.ux.colors.multiBlue('\u2022Command');
80 const workflowText = this.ux.colors.multiOrange('\u2022Workflow');
81 const { selectedOpOrWorkflow } = await this.ux.prompt({
82 type: 'autocomplete',
83 name: 'selectedOpOrWorkflow',
84 pageSize: 5,
85 message: `\nSelect a public ${commandText} or ${workflowText} to continue ${this.ux.colors.reset.green('ā†’')}\n${this.ux.colors.reset.dim('šŸ” Search:')} `,
86 source: this._autocompleteSearch.bind(this),
87 bottomContent: `\n \n${this.ux.colors.white(`Or, run ${this.ux.colors.callOutCyan('ops help')} for usage information.`)}`,
88 });
89 return Object.assign(Object.assign({}, inputs), { selectedOpOrWorkflow });
90 };
91 this.showRunMessage = (inputs) => {
92 const { selectedOpOrWorkflow: { name, teamName }, } = inputs;
93 this.log(`\nšŸ’» Run ${this.ux.colors.green('$')} ${this.ux.colors.italic.dim('ops run @' + teamName + '/' + name)} to test your op. \n`);
94 return inputs;
95 };
96 this.sendAnalytics = (filter) => async (inputs) => {
97 const { selectedOpOrWorkflow, selectedOpOrWorkflow: { id: opId, teamID }, } = inputs;
98 const teamOp = teamID === this.team.id;
99 const remote = 'remote' in selectedOpOrWorkflow ? selectedOpOrWorkflow.remote : false;
100 try {
101 this.services.analytics.track({
102 userId: this.user.email,
103 teamId: this.team.id,
104 cliEvent: 'Ops CLI Search',
105 event: 'Ops CLI Search',
106 properties: {
107 email: this.user.email,
108 username: this.user.username,
109 selectedOp: opId,
110 teamOp,
111 remote,
112 results: this.opsAndWorkflows.length,
113 filter,
114 },
115 }, this.accessToken);
116 }
117 catch (err) {
118 this.debug('%O', err);
119 throw new CustomErrors_1.AnalyticsError(err);
120 }
121 };
122 this._autocompleteSearch = async (_, input = '') => {
123 const { list, options } = this.fuzzyFilterParams();
124 const fuzzyResult = fuzzy_1.default.filter(input, list, options);
125 return fuzzyResult.map(result => result.original);
126 };
127 this.fuzzyFilterParams = () => {
128 const list = this.opsAndWorkflows.map(opOrWorkflow => {
129 const name = this._formatOpOrWorkflowName(opOrWorkflow);
130 return {
131 name: `${name} - ${opOrWorkflow.description}`,
132 value: opOrWorkflow,
133 };
134 });
135 const options = { extract: el => el.name };
136 return { list, options };
137 };
138 this._formatOpOrWorkflowName = (opOrWorkflow) => {
139 const teamName = opOrWorkflow.teamName ? `@${opOrWorkflow.teamName}/` : '';
140 const name = `${this.ux.colors.reset.white(`${teamName}${opOrWorkflow.name}`)} ${this.ux.colors.reset.dim(`(${opOrWorkflow.version})`)}`;
141 if (opOrWorkflow.type === opConfig_1.WORKFLOW_TYPE) {
142 return `${this.ux.colors.reset(this.ux.colors.multiOrange('\u2022'))} ${name}`;
143 }
144 else {
145 return `${this.ux.colors.reset(this.ux.colors.multiBlue('\u2022'))} ${name}`;
146 }
147 };
148 this.startSpinner = async (inputs) => {
149 await this.ux.spinner.start(`šŸ” ${this.ux.colors.white('Searching')} ${this.ux.colors.callOutCyan(`all ${utils_1.pluralize(opConfig_1.COMMAND)} and ${utils_1.pluralize(opConfig_1.WORKFLOW)}`)}`);
150 return inputs;
151 };
152 this.stopSpinner = async (inputs) => {
153 await this.ux.spinner.stop(`${this.ux.colors.successGreen('Done')}`);
154 return inputs;
155 };
156 }
157 async run() {
158 const { args: { filter = '' }, } = this.parse(Search);
159 try {
160 await this.isLoggedIn();
161 const searchPipeline = asyncPipe_1.asyncPipe(this.startSpinner, this.getApiOps, this.getLocalWorkflows, this.filterLocalWorkflows, this.resolveLocalAndApi, this.checkData, this.stopSpinner, this.selectOpOrWorkflowPrompt, this.showRunMessage, this.sendAnalytics(filter));
162 await searchPipeline(filter);
163 }
164 catch (err) {
165 await this.ux.spinner.stop(`${this.ux.colors.errorRed('Failed')}`);
166 this.debug('%O', err);
167 this.config.runHook('error', { err, accessToken: this.accessToken });
168 }
169 }
170}
171exports.default = Search;
172Search.description = 'Search for ops in your workspaces.';
173Search.args = [
174 {
175 name: 'filter',
176 description: 'Filters Op results which include filter text in Op name or description.',
177 },
178];
179Search.flags = {
180 help: base_1.flags.help({ char: 'h' }),
181};