#!/usr/bin/env node import fs from 'fs-extra'; import mustache from 'mustache'; import { program } from 'commander'; import { log, logSuccess, logInfo, logWarning, logError, colors } from './src/utils/logger'; import { checkOpenApiGenerator, installOpenApiGenerator } from './src/utils/openapi-generator'; import { createDirectoryStructure, cleanup } from './src/utils/filesystem'; import { analyzeSwagger } from './src/swagger/analyzer'; import { generateCode, organizeFiles } from './src/generators/dto.generator'; import { generateCleanArchitecture } from './src/generators/clean-arch.generator'; import { generateReport } from './src/generators/report.generator'; import type { CliOptions } from './src/types'; // Desactivar escape HTML para que los literales < y > generen tipos genéricos válidos de TS. (mustache as { escape: (text: string) => string }).escape = function (text: string): string { return text; }; // ── CLI CONFIGURATION ──────────────────────────────────────────────────────── program .name('generate-clean-arch') .description('Generador de código Angular con Clean Architecture desde OpenAPI/Swagger') .version('1.0.0') .option('-i, --input ', 'Archivo OpenAPI/Swagger (yaml o json)', 'swagger.yaml') .option('-o, --output ', 'Directorio de salida', './src/app') .option('-t, --templates ', 'Directorio de templates personalizados', './templates') .option('--skip-install', 'No instalar dependencias') .option('--dry-run', 'Simular sin generar archivos') .parse(process.argv); const options = program.opts(); // ── MAIN ORCHESTRATOR ──────────────────────────────────────────────────────── async function main(): Promise { console.log('\n' + '='.repeat(60)); log(' OpenAPI Clean Architecture Generator', 'bright'); log(' Angular + Clean Architecture Code Generator', 'cyan'); console.log('='.repeat(60) + '\n'); if (!fs.existsSync(options.input)) { logError(`Archivo no encontrado: ${options.input}`); process.exit(1); } logInfo(`Archivo de entrada: ${options.input}`); logInfo(`Directorio de salida: ${options.output}`); logInfo(`Templates: ${options.templates}`); if (options.dryRun) { logWarning('Modo DRY RUN - No se generarán archivos'); } if (!checkOpenApiGenerator()) { logWarning('OpenAPI Generator CLI no encontrado'); if (!options.skipInstall) { installOpenApiGenerator(); } else { logError( 'Instala openapi-generator-cli con: npm install -g @openapitools/openapi-generator-cli' ); process.exit(1); } } else { logSuccess('OpenAPI Generator CLI encontrado'); } const analysis = analyzeSwagger(options.input); if (options.dryRun) { logInfo('Finalizando en modo DRY RUN'); return; } createDirectoryStructure(options.output); const tempDir = generateCode(options.input, options.templates); organizeFiles(tempDir, options.output); generateCleanArchitecture(analysis, options.output, options.templates); cleanup(tempDir); const report = generateReport(options.output, analysis); console.log('\n' + '='.repeat(60)); log(' ✨ Generación completada con éxito', 'green'); console.log('='.repeat(60)); console.log(`\n📊 Resumen:`); console.log(` - DTOs generados: ${report.structure.dtos}`); console.log(` - Repositories: ${report.structure.repositories}`); console.log(` - Mappers: ${report.structure.mappers}`); console.log(` - Use Cases: ${report.structure.useCases}`); console.log(` - Providers: ${report.structure.providers}`); console.log(`\n📁 Archivos generados en: ${colors.cyan}${options.output}${colors.reset}\n`); } main().catch((error: unknown) => { const err = error as Error; logError(`Error fatal: ${err.message}`); console.error(error); process.exit(1); });