UNPKG

@cto.ai/ops

Version:

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

182 lines (181 loc) • 8.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const fuzzy_1 = tslib_1.__importDefault(require("fuzzy")); const fs = tslib_1.__importStar(require("fs-extra")); const path = tslib_1.__importStar(require("path")); const base_1 = tslib_1.__importStar(require("../base")); const asyncPipe_1 = require("../utils/asyncPipe"); const CustomErrors_1 = require("../errors/CustomErrors"); const opConfig_1 = require("../constants/opConfig"); const utils_1 = require("../utils"); class Search extends base_1.default { constructor() { super(...arguments); this.opsAndWorkflows = []; this.getApiOps = async (inputs) => { try { const findResponse = await this.services.api.find(`/private/ops`, { headers: { Authorization: this.accessToken, }, }); let { data: apiOps } = findResponse; apiOps = apiOps.filter(op => op.type !== opConfig_1.GLUECODE_TYPE); return Object.assign(Object.assign({}, inputs), { apiOps }); } catch (err) { this.debug('error: %O', err); throw new CustomErrors_1.APIError(err); } }; this.getLocalWorkflows = async (inputs) => { const localWorkflows = []; try { const manifest = await fs.readFile(path.join(process.cwd(), opConfig_1.OP_FILE), 'utf8'); if (!manifest) return inputs; const { workflows = [] } = utils_1.parseYaml(manifest); workflows.forEach(workflow => (workflow.local = true)); return Object.assign(Object.assign({}, inputs), { localWorkflows: workflows }); } catch (_a) { return Object.assign(Object.assign({}, inputs), { localWorkflows }); } }; this._removeIfNameOrDescriptionDontContainQuery = (filter) => (workflow) => { return (workflow.name.includes(filter) || workflow.description.includes(filter)); }; this.filterLocalWorkflows = (inputs) => { let { localWorkflows, filter } = inputs; if (!localWorkflows.length) return inputs; localWorkflows = localWorkflows.filter(this._removeIfNameOrDescriptionDontContainQuery(filter)); return Object.assign(Object.assign({}, inputs), { localWorkflows }); }; this._removeIfLocalExists = (workflows) => (apiOp) => { const match = workflows.find(workflow => workflow.name === apiOp.name); return !match; }; this.resolveLocalAndApi = (inputs) => { const { apiOps, localWorkflows } = inputs; const ops = apiOps.filter(this._removeIfLocalExists(localWorkflows)); this.opsAndWorkflows = [...ops, ...localWorkflows].sort((a, b) => { if (a.name < b.name) return -1; if (b.name < a.name) return 1; return 0; }); return inputs; }; this.checkData = async (inputs) => { if (!this.opsAndWorkflows.length) { 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`); } return inputs; }; this.selectOpOrWorkflowPrompt = async (inputs) => { const commandText = this.ux.colors.multiBlue('\u2022Command'); const workflowText = this.ux.colors.multiOrange('\u2022Workflow'); const { selectedOpOrWorkflow } = await this.ux.prompt({ type: 'autocomplete', name: 'selectedOpOrWorkflow', pageSize: 5, message: `\nSelect a public ${commandText} or ${workflowText} to continue ${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.`)}`, }); return Object.assign(Object.assign({}, inputs), { selectedOpOrWorkflow }); }; this.showRunMessage = (inputs) => { const { selectedOpOrWorkflow: { name, teamName }, } = inputs; this.log(`\nšŸ’» Run ${this.ux.colors.green('$')} ${this.ux.colors.italic.dim('ops run @' + teamName + '/' + name)} to test your op. \n`); return inputs; }; this.sendAnalytics = (filter) => async (inputs) => { const { selectedOpOrWorkflow, selectedOpOrWorkflow: { id: opId, teamID }, } = inputs; const teamOp = teamID === this.team.id; const remote = 'remote' in selectedOpOrWorkflow ? selectedOpOrWorkflow.remote : false; try { this.services.analytics.track({ userId: this.user.email, teamId: this.team.id, cliEvent: 'Ops CLI Search', event: 'Ops CLI Search', properties: { email: this.user.email, username: this.user.username, selectedOp: opId, teamOp, remote, results: this.opsAndWorkflows.length, filter, }, }, this.accessToken); } catch (err) { this.debug('%O', err); throw new CustomErrors_1.AnalyticsError(err); } }; 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.fuzzyFilterParams = () => { const list = this.opsAndWorkflows.map(opOrWorkflow => { const name = this._formatOpOrWorkflowName(opOrWorkflow); return { name: `${name} - ${opOrWorkflow.description}`, value: opOrWorkflow, }; }); const options = { extract: el => el.name }; return { list, options }; }; this._formatOpOrWorkflowName = (opOrWorkflow) => { const teamName = opOrWorkflow.teamName ? `@${opOrWorkflow.teamName}/` : ''; const name = `${this.ux.colors.reset.white(`${teamName}${opOrWorkflow.name}`)} ${this.ux.colors.reset.dim(`(${opOrWorkflow.version})`)}`; if (opOrWorkflow.type === opConfig_1.WORKFLOW_TYPE) { return `${this.ux.colors.reset(this.ux.colors.multiOrange('\u2022'))} ${name}`; } else { return `${this.ux.colors.reset(this.ux.colors.multiBlue('\u2022'))} ${name}`; } }; this.startSpinner = async (inputs) => { 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)}`)}`); return inputs; }; this.stopSpinner = async (inputs) => { await this.ux.spinner.stop(`${this.ux.colors.successGreen('Done')}`); return inputs; }; } async run() { const { args: { filter = '' }, } = this.parse(Search); try { await this.isLoggedIn(); 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)); await searchPipeline(filter); } catch (err) { await this.ux.spinner.stop(`${this.ux.colors.errorRed('Failed')}`); this.debug('%O', err); this.config.runHook('error', { err, accessToken: this.accessToken }); } } } exports.default = Search; Search.description = 'Search for ops in your workspaces.'; Search.args = [ { name: 'filter', description: 'Filters Op results which include filter text in Op name or description.', }, ]; Search.flags = { help: base_1.flags.help({ char: 'h' }), };