import { Command } from 'commander'; import inquirer from 'inquirer'; import { parse, stringify } from 'yaml'; import Fuse from 'fuse.js'; import fs from 'fs'; import path from 'path'; import { v4 } from 'uuid'; import { getProjectPath } from '../../../../helpers/cluserHelper'; import { getConnectors } from './connectors'; import { connectionYaml } from '../../../../components/connectionTemplate'; import { mergeVariables } from '../../../../helpers/variablesHelper'; async function searchConnector(options): Promise { const fuse = new Fuse(getConnectors(), { includeScore: true, keys: [ 'name', // will be assigned a `weight` of 1 { name: 'tags', weight: 2, }, ], }); const result = fuse .search(options.tags) .sort((a: any, b: any) => parseFloat(a.score) - parseFloat(b.score)); if (result.length === 0) { console.log(`There is no such connector ${options.tags}`); return null; } // Use a single-choice list for connector selection const answer = await inquirer.prompt<{ selectedConnector: any }>([ { type: 'list', name: 'selectedConnector', message: 'Please select a connector:', choices: result.map((x: any, i) => ({ name: `${i + 1}. ${x.item.name}`, value: x.item, })), }, ]); return answer.selectedConnector; } async function getConnectionInfo(connector, options) { console.log(`Enter name of the connection.`); const answer = await inquirer.prompt<{ value: string }>([ { type: 'input', name: 'value', message: `Answer (default ${connector.name}):`, }, ]); const value = answer.value || connector.name; let keyName = value.replace(/[^a-zA-Z0-9]+/g, ''); let connectionName = value; let fileName = keyName; const componentPath = getProjectPath(); let filePath = path.join(componentPath, `${keyName}Connection.yaml`); let fileIndex = 0; while (true) { if (fs.existsSync(filePath) && !options.overwrite) { fileIndex++; connectionName = `${value} ${fileIndex}`; fileName = `${keyName}${fileIndex}`; filePath = path.join(componentPath, `${fileName}Connection.yaml`); continue; } break; } return { connectionName, fileName }; } function parseConfig( connectionInfo: { connectionName: string; fileName: string }, connector: any, ): { config: any; variables: Array<{ key: string; value: any }> } { let config = parse(connectionYaml()) as any; const connectionId = v4(); const connectionIdKey = `**${connectionInfo.fileName}ConnectionId**`; const connectionNameKey = `**${connectionInfo.fileName}ConnectionName**`; let variables = [ { key: connectionIdKey, value: connectionId, }, { key: connectionNameKey, value: connectionInfo.connectionName, }, ]; config['connectors'][0].id = connectionIdKey; config['connectors'][0].name = connectionNameKey; config['connectors'][0].providerId = connector.connectorId; config['connectors'][0].description = ''; return { config, variables }; } export function GenerateConnectionCommand(): Command { const cmd = new Command('generate') .alias('g') .description('Generates a HexaSync Connection') .option('-t, --tags ', 'Search by name or tags') .option('-w, --overwrite', 'Overwrite existing connector') .action(async (options) => { console.log('Generating a HexaSync Connection', options); const connector = await searchConnector(options); const connectionInfo = await getConnectionInfo(connector, options); const config = parseConfig(connectionInfo, connector); // write variables mergeVariables(config.variables); // write connection to project/partials/.yaml const componentPath = getProjectPath(); const connectionFilePath = path.join( componentPath, `${connectionInfo.fileName}Connection.yaml`, ); if (fs.existsSync(connectionFilePath)) { console.error(`There is a file exists in ${connectionFilePath}`); return; } fs.writeFileSync(connectionFilePath, stringify(config.config)); }); return cmd; }