import { Command } from 'commander'; import fs from 'fs'; import { stringify } from 'yaml'; import { findTable, searchTask, searchReport, searchSchema, getAssociation, } from '../../helpers/profileGeneratorHelper'; import inquirer from 'inquirer'; export function SetIndexGroupsCommand(): Command { const cmd = new Command('set-index-groups'); cmd .alias('si') .description('Add or update index groups for a table.') .option( '-t, --type ', 'Type of the table, e.g., task, report, schema', ) .option('-n, --name ', 'Search the entity by name') .action(async ({ type, name }) => { let table: any; switch (type.toLowerCase()) { case 'task': case 'object': const task = await searchTask(name); if (!task) { console.error(`Task "${name}" not found.`); return; } const associations = getAssociation(); const taskAssociation = associations.objectAssociations[task.id]; table = findTable(taskAssociation?.table?.id); break; case 'report': const report = await searchReport(name); if (!report) { console.error(`Report "${name}" not found.`); return; } table = findTable(report.tableId); break; case 'schema': const schema = await searchSchema(name); if (!schema) { console.error(`Schema "${name}" not found.`); return; } table = findTable(schema.tableId); break; default: console.error( `Unsupported type "${type}". Supported types: task, report, schema.`, ); return; } if (!table) { console.error(`Table associated with "${name}" not found.`); return; } console.log('Existing Index Groups in the Table:'); Object.entries(table.indexGroups || {}).forEach(([name, details]) => { const indexGroupDetails = details as { type: string }; console.log(`- ${name}: Type = ${indexGroupDetails.type}`); }); const { action } = await inquirer.prompt([ { type: 'list', name: 'action', message: 'What would you like to do with the index groups?', choices: [ { name: 'Update columns for existing index groups', value: 'update', }, { name: 'Overwrite all index groups', value: 'overwrite' }, { name: 'Add new index groups', value: 'add' }, ], }, ]); if (action === 'update') { if (!table.indexGroups || Object.keys(table.indexGroups).length === 0) { console.error('No existing index groups to update.'); return; } for (const [groupName, details] of Object.entries(table.indexGroups)) { console.log(`Updating columns for index group: ${groupName}`); const { columns } = await inquirer.prompt([ { type: 'checkbox', name: 'columns', message: `Select columns to associate with index group "${groupName}" (currently associated: ${Object.keys( table.columns, ) .filter((col) => table.columns[col].indexGroups?.includes(groupName), ) .join(', ')}):`, choices: Object.keys(table.columns).map((col) => ({ name: col, value: col, checked: table.columns[col]?.indexGroups?.includes(groupName), })), }, ]); Object.keys(table.columns).forEach((col) => { table.columns[col].indexGroups = table.columns[col].indexGroups?.filter( (group) => group !== groupName, ) || []; }); columns.forEach((col) => { table.columns[col].indexGroups = table.columns[col].indexGroups || []; table.columns[col].indexGroups.push(groupName); }); } } if (action === 'overwrite') { console.warn( 'You are about to overwrite all existing index groups. This action cannot be undone.', ); const { confirmOverwrite } = await inquirer.prompt([ { type: 'confirm', name: 'confirmOverwrite', message: 'Are you sure you want to overwrite all index groups?', default: false, }, ]); if (!confirmOverwrite) { console.log('Operation cancelled.'); return; } table.indexGroups = {}; Object.keys(table.columns).forEach((col) => { table.columns[col].indexGroups = []; }); } if (action === 'add' || action === 'overwrite') { const { indexGroups } = await inquirer.prompt([ { type: 'input', name: 'indexGroups', message: 'Enter the names of the new index groups (comma-separated):', }, ]); const indexGroupNames = indexGroups .split(',') .map((name) => name .trim() .replace(/[^a-zA-Z0-9\s]/g, '') .replace(/\s+/g, '_') .toUpperCase(), ) .filter(Boolean); if (indexGroupNames.length === 0) { console.error('No valid index groups provided.'); return; } const indexGroupDetails = {}; for (const groupName of indexGroupNames) { const { groupType } = await inquirer.prompt([ { type: 'list', name: 'groupType', message: `Select the type of index group "${groupName}":`, choices: ['UNIQUE', 'COMMON', 'HASH'], }, ]); indexGroupDetails[groupName] = { type: groupType }; } for (const groupName of indexGroupNames) { const { columns } = await inquirer.prompt([ { type: 'checkbox', name: 'columns', message: `Select columns to associate with index group "${groupName}":`, choices: Object.keys(table.columns).map((col) => ({ name: col, value: col, })), }, ]); if (columns.length === 0) { console.error( `No columns selected for index group "${groupName}". Skipping.`, ); continue; } columns.forEach((col) => { table.columns[col].indexGroups = table.columns[col].indexGroups || []; if (!table.columns[col].indexGroups.includes(groupName)) { table.columns[col].indexGroups.push(groupName); } }); } table.indexGroups = table.indexGroups || {}; Object.assign(table.indexGroups, indexGroupDetails); } const filePath = table.__file_path; if (!filePath) { throw new Error(`Could not find table file path.`); } delete table.__file_path; delete table.__real_name; fs.writeFileSync( filePath, stringify( { tables: [{ ...table }] }, { keepSourceTokens: true, lineWidth: 0 }, ), ); console.log( `Done. Please double-check the index groups and column associations.`, ); }); return cmd; }