import prompts from 'prompts'; import { ApiKeyInfo } from './environment-finder'; import { colors } from './logger'; import type { TagSummary, SelectionFilter } from '../types'; function clearScreen(): void { process.stdout.write('\x1Bc'); } function printHeader(current?: number, total?: number): void { const stepText = current !== undefined && total !== undefined ? ` [${colors.cyan}${current}${colors.reset} de ${colors.cyan}${total}${colors.reset}]` : ''; console.log(`\n ${colors.bright}🔑 Configuración de URLs base${colors.reset}${stepText}`); console.log(` ${'─'.repeat(54)}\n`); } function printSummary(tags: string[], result: Record): void { clearScreen(); console.log(`\n ${colors.bright}✅ Configuración completada${colors.reset}`); console.log(` ${'─'.repeat(54)}\n`); tags.forEach((tag) => { console.log(` ${colors.bright}${tag}${colors.reset}`); console.log(` ${colors.cyan}environment.${result[tag]}.url${colors.reset}\n`); }); console.log(` ${'─'.repeat(54)}\n`); } /** * Interactively asks the user which tags and endpoints to generate. * Returns a SelectionFilter map of tag → selected operation nicknames. */ export async function askSelectionFilter(tagSummaries: TagSummary[]): Promise { if (tagSummaries.length === 0) return {}; clearScreen(); console.log(`\n ${colors.bright}📋 Selección de tags y endpoints${colors.reset}`); console.log(` ${'─'.repeat(54)}\n`); // Step 1: select tags const tagResponse = await prompts({ type: 'multiselect', name: 'tags', message: 'Tags a generar', choices: tagSummaries.map((t) => ({ title: `${colors.bright}${t.tag}${colors.reset} ${colors.cyan}(${t.operations.length} endpoint${t.operations.length !== 1 ? 's' : ''})${colors.reset}`, value: t.tag, selected: true })), min: 1, hint: 'Espacio para marcar/desmarcar, Enter para confirmar' }); if (!tagResponse.tags?.length) process.exit(0); const selectedTags: string[] = tagResponse.tags; const filter: SelectionFilter = {}; // Step 2: for each selected tag, select endpoints for (let i = 0; i < selectedTags.length; i++) { const tag = selectedTags[i]; const summary = tagSummaries.find((t) => t.tag === tag)!; clearScreen(); console.log( `\n ${colors.bright}📋 Endpoints a generar${colors.reset} [${colors.cyan}${i + 1}${colors.reset} de ${colors.cyan}${selectedTags.length}${colors.reset}]` ); console.log(` ${'─'.repeat(54)}\n`); const opResponse = await prompts({ type: 'multiselect', name: 'ops', message: `Tag ${colors.bright}${tag}${colors.reset}`, choices: summary.operations.map((op) => ({ title: `${colors.bright}${op.method.padEnd(6)}${colors.reset} ${op.path}` + (op.summary ? ` ${colors.cyan}${op.summary}${colors.reset}` : ''), value: op.nickname, selected: true })), min: 1, hint: 'Espacio para marcar/desmarcar, Enter para confirmar' }); if (!opResponse.ops?.length) process.exit(0); filter[tag] = opResponse.ops; } return filter; } /** * Interactively asks the user which environment API key to use for each tag, * using arrow-key selection. The last option always allows typing manually. * Returns a map of tag → environment key (e.g. { "SupplyingMaintenances": "suppliyingMaintenancesApi" }). */ export async function askApiKeysForTags( tags: string[], apiKeys: ApiKeyInfo[] ): Promise> { if (tags.length === 0) return {}; clearScreen(); printHeader(); const modeResponse = await prompts({ type: 'select', name: 'mode', message: 'URL base para los repositorios', choices: [ { title: `${colors.bright}La misma para todos${colors.reset}`, value: 'all' }, { title: `${colors.bright}Configurar individualmente${colors.reset}`, value: 'individual' } ], hint: ' ' }); if (modeResponse.mode === undefined) process.exit(0); const result: Record = {}; if (modeResponse.mode === 'all') { clearScreen(); printHeader(); const sharedKey = await askApiKeyForTag('todos los repositorios', apiKeys); tags.forEach((tag) => (result[tag] = sharedKey)); } else { for (let i = 0; i < tags.length; i++) { clearScreen(); printHeader(i + 1, tags.length); result[tags[i]] = await askApiKeyForTag(tags[i], apiKeys); } } printSummary(tags, result); return result; } async function askApiKeyForTag(tagName: string, apiKeys: ApiKeyInfo[]): Promise { const MANUAL_VALUE = '__manual__'; const choices = [ ...apiKeys.map((k) => ({ title: k.url ? `${colors.bright}${k.key}${colors.reset}\n ${colors.cyan}↳ ${k.url}${colors.reset}` : `${colors.bright}${k.key}${colors.reset}`, value: k.key })), { title: `${colors.bright}Escribir manualmente${colors.reset}`, value: MANUAL_VALUE } ]; const selectResponse = await prompts({ type: 'select', name: 'key', message: `Repositorio ${colors.bright}${tagName}${colors.reset}`, choices, hint: ' ' }); if (selectResponse.key === undefined) process.exit(0); if (selectResponse.key !== MANUAL_VALUE) { return selectResponse.key as string; } console.log(); const textResponse = await prompts({ type: 'text', name: 'key', message: `Clave de environment`, hint: 'ej: aprovalmApi', validate: (v: string) => v.trim().length > 0 || 'La clave no puede estar vacía' }); if (textResponse.key === undefined) process.exit(0); return (textResponse.key as string).trim(); }