- Added `clean-arch.generator.ts` for generating models, mappers, repositories, use cases, and providers based on OpenAPI specs. - Introduced `dto.generator.ts` to invoke `openapi-generator-cli` for generating DTOs and organizing them. - Created `report.generator.ts` to generate a JSON report of the generation process. - Implemented `analyzer.ts` for parsing OpenAPI/Swagger files and extracting relevant data. - Defined new types in `cli.types.ts`, `generation.types.ts`, `openapi.types.ts`, and `swagger.types.ts` for better type safety. - Added utility functions in `filesystem.ts` for creating directory structures and cleaning up temporary files. - Developed logging utilities in `logger.ts` for better console output. - Included OpenAPI generator checks and installation in `openapi-generator.ts`. - Added type mapping utility in `type-mapper.ts` for converting OpenAPI types to TypeScript types. - Updated `package.json` scripts to lint all TypeScript files. - Modified `tsconfig.json` to include all TypeScript files in the project.
105 lines
4.0 KiB
JavaScript
Executable File
105 lines
4.0 KiB
JavaScript
Executable File
#!/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 <file>', 'Archivo OpenAPI/Swagger (yaml o json)', 'swagger.yaml')
|
|
.option('-o, --output <dir>', 'Directorio de salida', './src/app')
|
|
.option('-t, --templates <dir>', '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<CliOptions>();
|
|
|
|
// ── MAIN ORCHESTRATOR ────────────────────────────────────────────────────────
|
|
|
|
async function main(): Promise<void> {
|
|
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);
|
|
});
|