UNPKG

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