184 lines
5.6 KiB
TypeScript
184 lines
5.6 KiB
TypeScript
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<string, string>): 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<SelectionFilter> {
|
|
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<Record<string, string>> {
|
|
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<string, string> = {};
|
|
|
|
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<string> {
|
|
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();
|
|
}
|