weaver-frontend-cli
Version:
🕷️ Weaver CLI - Generador completo de arquitectura Clean Architecture para entidades CRUD y flujos de negocio desde OpenAPI/Swagger
276 lines • 13.7 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectValidator = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const chalk_1 = __importDefault(require("chalk"));
class ProjectValidator {
/**
* Valida que la estructura del proyecto sea la correcta
*/
static async validateProjectStructure(basePath, apiName = 'platform') {
console.log(chalk_1.default.blue('🔍 Validando estructura del proyecto...'));
// Determinar si estamos en el directorio de la API o necesitamos crear uno
const currentDirName = path.basename(basePath);
const shouldCreateApiDir = currentDirName !== apiName;
const apiPrefix = shouldCreateApiDir ? `${apiName}/` : '';
const requiredDirectories = [
`${apiPrefix}domain/models/apis/${apiName}/entities`,
`${apiPrefix}domain/services/repositories/apis/${apiName}/entities`,
`${apiPrefix}domain/services/use_cases/apis/${apiName}/entities`,
`${apiPrefix}infrastructure/entities/apis/${apiName}/entities`,
`${apiPrefix}infrastructure/mappers/apis/${apiName}/entities`,
`${apiPrefix}infrastructure/repositories/apis/${apiName}/repositories/entities`,
`${apiPrefix}facade/apis/${apiName}/entities`
];
const missingDirectories = [];
const warnings = [];
// Verificar que el directorio base existe
if (!await fs.pathExists(basePath)) {
return {
isValid: false,
message: `❌ El directorio base no existe: ${basePath}`
};
}
// Verificar directorios requeridos
for (const dir of requiredDirectories) {
const fullPath = path.join(basePath, dir);
if (!await fs.pathExists(fullPath)) {
missingDirectories.push(dir);
}
}
// Verificar archivos de configuración clave
const coreFiles = [
'core/interfaces/index.ts',
'core/classes/index.ts',
'core/axios/platform-axios.ts'
];
for (const file of coreFiles) {
const fullPath = path.join(basePath, file);
if (!await fs.pathExists(fullPath)) {
warnings.push(`⚠️ Archivo core no encontrado: ${file}`);
}
}
// Ser más permisivo - no bloquear por directorios faltantes
if (missingDirectories.length > 0) {
warnings.push(`Se crearán los directorios faltantes automáticamente: ${missingDirectories.length} directorios`);
}
// Verificar que parece ser un proyecto goluti-frontend
const indicatorFiles = [
'core/const/const-platform-api-routes.ts',
'core/injection/injection-core.ts'
];
let projectIndicators = 0;
for (const file of indicatorFiles) {
const fullPath = path.join(basePath, file);
if (await fs.pathExists(fullPath)) {
projectIndicators++;
}
}
if (projectIndicators === 0) {
warnings.push('⚠️ No se detectaron archivos característicos del proyecto goluti-frontend');
}
return {
isValid: true,
message: '✅ Estructura del proyecto válida',
warnings
};
}
/**
* Verifica si una entidad ya existe en el proyecto
*/
static async checkEntityExists(entityName, basePath, apiName = 'platform') {
const entityNameLower = entityName.toLowerCase();
const entityNameKebab = entityName.replace(/([A-Z])/g, '-$1').toLowerCase().substring(1);
console.log(chalk_1.default.blue(`🔍 Verificando si la entidad "${entityName}" ya existe...`));
const conflictingFiles = [];
// Determinar si estamos en el directorio de la API o necesitamos crear uno
const currentDirName = path.basename(basePath);
const shouldCreateApiDir = currentDirName !== apiName;
const apiPrefix = shouldCreateApiDir ? `${apiName}/` : '';
// Directorios donde buscar archivos de la entidad (usando apiName dinámico)
const searchPaths = [
`${apiPrefix}domain/models/apis/${apiName}/entities/${entityNameLower}`,
`${apiPrefix}domain/services/repositories/apis/${apiName}/entities/i-${entityNameKebab}-repository.ts`,
`${apiPrefix}domain/services/use_cases/apis/${apiName}/entities/${entityNameLower}`,
`${apiPrefix}infrastructure/entities/apis/${apiName}/entities/${entityNameLower}`,
`${apiPrefix}infrastructure/mappers/apis/${apiName}/entities/${entityNameLower}`,
`${apiPrefix}infrastructure/repositories/apis/${apiName}/repositories/entities/${entityNameLower}`,
`${apiPrefix}facade/apis/${apiName}/entities/${entityNameKebab}-facade.ts`
];
for (const searchPath of searchPaths) {
const fullPath = path.join(basePath, searchPath);
if (await fs.pathExists(fullPath)) {
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) {
// Si es directorio, verificar si tiene archivos
const files = await fs.readdir(fullPath);
if (files.length > 0) {
conflictingFiles.push(`📁 ${searchPath}/ (${files.length} archivos)`);
}
}
else {
// Si es archivo
conflictingFiles.push(`📄 ${searchPath}`);
}
}
}
const exists = conflictingFiles.length > 0;
return {
exists,
conflictingFiles,
message: exists
? `⚠️ La entidad "${entityName}" ya existe parcial o completamente`
: `✅ La entidad "${entityName}" no existe, se puede generar`
};
}
/**
* Verifica si una entidad de negocio ya existe en el proyecto
*/
static async checkBusinessEntityExists(entityName, basePath, apiName = 'platform') {
const entityNameLower = entityName.toLowerCase();
const entityNameKebab = entityName.replace(/([A-Z])/g, '-$1').toLowerCase().substring(1);
const conflictingFiles = [];
// Determinar si estamos en el directorio de la API o necesitamos crear uno
const currentDirName = path.basename(basePath);
const shouldCreateApiDir = currentDirName !== apiName;
const apiPrefix = shouldCreateApiDir ? `${apiName}/` : '';
// Directorios donde buscar archivos de la entidad de negocio (usando business en lugar de entities)
const searchPaths = [
`${apiPrefix}domain/models/apis/${apiName}/business/${entityNameLower}`,
`${apiPrefix}domain/services/repositories/apis/${apiName}/business/i-${entityNameKebab}-repository.ts`,
`${apiPrefix}domain/services/use_cases/apis/${apiName}/business/${entityNameLower}`,
`${apiPrefix}infrastructure/entities/apis/${apiName}/business/${entityNameLower}`,
`${apiPrefix}infrastructure/mappers/apis/${apiName}/business/${entityNameLower}`,
`${apiPrefix}infrastructure/repositories/apis/${apiName}/repositories/business/${entityNameLower}`,
`${apiPrefix}facade/apis/${apiName}/business/${entityNameKebab}-facade.ts`
];
for (const searchPath of searchPaths) {
const fullPath = path.join(basePath, searchPath);
if (await fs.pathExists(fullPath)) {
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) {
// Si es directorio, verificar si tiene archivos
const files = await fs.readdir(fullPath);
if (files.length > 0) {
conflictingFiles.push(`📁 ${searchPath}/ (${files.length} archivos)`);
}
}
else {
// Si es archivo
conflictingFiles.push(`📄 ${searchPath}`);
}
}
}
const exists = conflictingFiles.length > 0;
return {
exists,
conflictingFiles: conflictingFiles,
message: exists
? `⚠️ La entidad de negocio "${entityName}" ya existe parcial o completamente`
: `✅ La entidad de negocio "${entityName}" no existe, se puede generar`
};
}
/**
* Valida la configuración completa antes de generar
*/
static async validateBeforeGeneration(entityName, basePath, apiName = 'platform') {
console.log(chalk_1.default.yellow('\n🔍 Ejecutando validaciones pre-generación...\n'));
const structureResult = await this.validateProjectStructure(basePath, apiName);
const entityResult = await this.checkEntityExists(entityName, basePath, apiName);
const recommendations = [];
let canProceed = structureResult.isValid;
// Mostrar resultados de validación
console.log(structureResult.message);
if (structureResult.warnings) {
structureResult.warnings.forEach(warning => console.log(chalk_1.default.yellow(warning)));
}
console.log(entityResult.message);
if (entityResult.conflictingFiles.length > 0) {
console.log(chalk_1.default.yellow('\nArchivos/directorios existentes:'));
entityResult.conflictingFiles.forEach(file => console.log(chalk_1.default.gray(` ${file}`)));
}
// Generar recomendaciones
if (!structureResult.isValid) {
recommendations.push('Verifica que estés ejecutando el comando en el directorio correcto del proyecto goluti-frontend');
canProceed = false;
}
if (entityResult.exists) {
recommendations.push('La entidad ya existe. Si continúas, se sobrescribirán los archivos existentes');
recommendations.push('Considera hacer un backup antes de continuar');
// No bloqueamos la generación, pero advertimos
}
if (structureResult.warnings && structureResult.warnings.length > 0) {
recommendations.push('Algunas dependencias core no fueron encontradas. El código generado podría necesitar ajustes');
}
return {
canProceed,
structureResult,
entityResult,
recommendations
};
}
/**
* Muestra un resumen de lo que se va a generar
*/
static showGenerationSummary(entityName, basePath, willOverwrite) {
const entityNameLower = entityName.toLowerCase();
const entityNameKebab = entityName.replace(/([A-Z])/g, '-$1').toLowerCase().substring(1);
console.log(chalk_1.default.blue('\n📋 Resumen de generación:'));
console.log(chalk_1.default.gray(`Entidad: ${entityName}`));
console.log(chalk_1.default.gray(`Ubicación: ${basePath}`));
console.log(chalk_1.default.gray(`Archivos a generar: ~29 archivos TypeScript`));
if (willOverwrite) {
console.log(chalk_1.default.yellow('⚠️ Se sobrescribirán archivos existentes'));
}
console.log(chalk_1.default.blue('\n📁 Directorios que se crearán/utilizarán:'));
const directories = [
`📂 domain/models/apis/platform/entities/${entityNameLower}/`,
`📂 domain/services/use_cases/apis/platform/entities/${entityNameLower}/`,
`📂 infrastructure/entities/apis/platform/entities/${entityNameLower}/`,
`📂 infrastructure/mappers/apis/platform/entities/${entityNameLower}/`,
`📂 infrastructure/repositories/.../entities/${entityNameLower}/`,
`📂 facade/apis/platform/entities/`,
`📂 injection folders...`
];
directories.forEach(dir => console.log(chalk_1.default.gray(` ${dir}`)));
}
}
exports.ProjectValidator = ProjectValidator;
//# sourceMappingURL=project-validator.js.map