UNPKG

sysrot-hub

Version:

CLI de nueva generación para proyectos Next.js 14+ con IA multi-modelo, Web3 integration, internacionalización completa y roadmap realista 2025-2026

470 lines (421 loc) 14.1 kB
#!/usr/bin/env node const { Command } = require('commander'); const inquirer = require('inquirer'); const chalk = require('chalk'); const { createProject } = require('./createProject'); const logger = require('./utils/logger'); const path = require('path'); const program = new Command(); // Funciones delegadas al logger function showLogo() { logger.showLogo(); logger.showFeatures(); } function showHelp() { logger.showHelp(); } // Available example templates with descriptions const AVAILABLE_EXAMPLES = [ { name: 'Analytics Dashboard', value: 'analytics-dashboard', description: 'Interactive dashboard with Chart.js and D3.js visualizations', dependencies: ['chart.js', 'react-chartjs-2', 'd3', '@types/d3'] }, { name: 'Modern Landing Page', value: 'landing-page', description: 'Professional landing page with multiple sections', dependencies: ['react-intersection-observer', 'react-parallax'] }, { name: 'E-commerce with Cart', value: 'ecommerce', description: 'Basic e-commerce with shopping cart functionality', dependencies: ['zustand', 'react-currency-input-field'] }, { name: 'Personal Portfolio', value: 'portfolio', description: 'Responsive personal portfolio showcase', dependencies: ['typed.js', 'react-scroll'] }, { name: 'Task Management App', value: 'task-app', description: 'Task app with local storage persistence', dependencies: ['use-local-storage-state', 'react-beautiful-dnd'] }, { name: 'Real-time Chat', value: 'chat', description: 'Real-time chat application with WebSockets', dependencies: ['socket.io-client', 'uuid', '@types/uuid'] }, { name: 'Multi-tenant SaaS', value: 'saas', description: 'Multi-tenant SaaS example with subscription management', dependencies: ['@stripe/stripe-js', 'stripe'] }, { name: 'Marketplace with Reviews', value: 'marketplace', description: 'Marketplace platform with ratings and reviews system', dependencies: ['react-rating-stars-component', 'react-image-gallery'] } ]; async function askProjectConfiguration() { console.log(chalk.blue('\n🛠️ Configuración del Proyecto\n')); const config = await inquirer.prompt([ { type: 'confirm', name: 'typescript', message: '🔷 ¿Deseas TypeScript configurado?', default: true }, { type: 'confirm', name: 'tailwindcss', message: '🎨 ¿Deseas TailwindCSS configurado?', default: true }, { type: 'confirm', name: 'eslint', message: '📏 ¿Deseas ESLint configurado?', default: true }, { type: 'list', name: 'database', message: '💾 ¿Qué base de datos deseas usar?', choices: [ { name: 'MongoDB', value: 'MongoDB' }, { name: 'Supabase', value: 'Supabase' }, { name: 'Firebase', value: 'Firebase' }, { name: 'Ninguna', value: 'None' } ], default: 'MongoDB' }, { type: 'confirm', name: 'auth', message: '🔐 ¿Deseas sistema de autenticación con NextAuth.js?', default: true } ]); // Preguntas condicionales para autenticación if (config.auth) { const authConfig = await inquirer.prompt([ { type: 'checkbox', name: 'authProviders', message: '🔑 Selecciona los proveedores de autenticación:', choices: [ { name: 'Google', value: 'Google', checked: true }, { name: 'GitHub', value: 'GitHub', checked: true }, { name: 'Email', value: 'Email' }, { name: 'Discord', value: 'Discord' }, { name: 'Twitter', value: 'Twitter' } ], validate: (answer) => { if (answer.length === 0) { return 'Debes seleccionar al menos un proveedor de autenticación.'; } return true; } }, { type: 'confirm', name: 'roles', message: '👤 ¿Deseas incluir sistema de roles básico (admin/user)?', default: true }, { type: 'confirm', name: 'middleware', message: '🛡️ ¿Deseas middleware de protección de rutas?', default: true } ]); Object.assign(config, authConfig); } // Continuar con más configuraciones const aiConfig = await inquirer.prompt([ { type: 'confirm', name: 'ai', message: '🤖 ¿Deseas integración con modelos de IA?', default: true } ]); if (aiConfig.ai) { const aiModels = await inquirer.prompt([ { type: 'checkbox', name: 'aiModels', message: '🧠 Selecciona los modelos de IA a integrar:', choices: [ { name: 'GPT-4o (OpenAI)', value: 'GPT-4o (OpenAI)', checked: true }, { name: 'Claude 3.5 (Anthropic)', value: 'Claude 3.5 (Anthropic)', checked: true }, { name: 'Gemini Flash Pro (Google)', value: 'Gemini Flash Pro (Google)', checked: true }, { name: 'DeepSeek V3 Chat', value: 'DeepSeek V3 Chat' }, { name: 'DeepSeek R1 Reasoner', value: 'DeepSeek R1 Reasoner' } ], validate: (answer) => { if (answer.length === 0) { return 'Debes seleccionar al menos un modelo de IA.'; } return true; } } ]); Object.assign(aiConfig, aiModels); } Object.assign(config, aiConfig); // Configuraciones adicionales const additionalConfig = await inquirer.prompt([ { type: 'confirm', name: 'cloudinary', message: '☁️ ¿Deseas integración con Cloudinary para carga de imágenes?', default: true }, { type: 'confirm', name: 'blog', message: '📝 ¿Deseas agregar un blog con MDX?', default: true } ]); if (additionalConfig.blog) { const blogFeatures = await inquirer.prompt([ { type: 'confirm', name: 'mdxFeatures', message: '✨ ¿Deseas características avanzadas de MDX (syntax highlighting, slugs automáticos)?', default: true } ]); Object.assign(additionalConfig, blogFeatures); } const uiConfig = await inquirer.prompt([ { type: 'confirm', name: 'forms', message: '📋 ¿Deseas integración de formularios (react-hook-form + zod)?', default: true }, { type: 'confirm', name: 'darkMode', message: '🌙 ¿Deseas integración de temas (modo claro/oscuro)?', default: true }, { type: 'confirm', name: 'uiComponents', message: '🎨 ¿Deseas componentes UI reutilizables (layout, iconos, botones)?', default: true }, { type: 'confirm', name: 'framerMotion', message: '🎬 ¿Deseas animaciones con framer-motion?', default: true }, { type: 'confirm', name: 'notifications', message: '🔔 ¿Deseas sistema de notificaciones toast (react-hot-toast)?', default: true } ]); Object.assign(config, additionalConfig, uiConfig); // Ejemplos funcionales const examplesConfig = await inquirer.prompt([ { type: 'confirm', name: 'examplePages', message: '📄 ¿Deseas incluir páginas de ejemplo funcionales?', default: true } ]); if (examplesConfig.examplePages) { const exampleTypes = await inquirer.prompt([ { type: 'checkbox', name: 'exampleTypes', message: '📚 Selecciona los ejemplos a incluir:', choices: [ { name: 'Ejemplo de Autenticación', value: 'Ejemplo de Autenticación', checked: true }, { name: 'Ejemplo de IA (Multi-modelo)', value: 'Ejemplo de IA (Multi-modelo)', checked: true }, { name: 'Biblioteca de Componentes', value: 'Biblioteca de Componentes', checked: true }, { name: 'Ejemplo de Carga de Imágenes', value: 'Ejemplo de Carga de Imágenes', checked: true }, { name: 'Ejemplo de Formularios', value: 'Ejemplo de Formularios', checked: true }, { name: 'Ejemplo de Animaciones', value: 'Ejemplo de Animaciones', checked: true }, { name: 'Ejemplo de Notificaciones', value: 'Ejemplo de Notificaciones', checked: true }, { name: 'Ejemplo de Base de Datos', value: 'Ejemplo de Base de Datos', checked: true }, { name: 'Ejemplo de UI y Temas', value: 'Ejemplo de UI y Temas', checked: true }, { name: 'Ejemplo de TypeScript', value: 'Ejemplo de TypeScript', checked: true } ] } ]); Object.assign(examplesConfig, exampleTypes); } Object.assign(config, examplesConfig); // Ejemplos de integración completa const fullIntegrationConfig = await inquirer.prompt([ { type: 'confirm', name: 'includeFullIntegrationExamples', message: '🎨 ¿Deseas incluir ejemplos de integración completa adicionales?', default: false } ]); if (fullIntegrationConfig.includeFullIntegrationExamples) { const fullIntegrationExamples = await inquirer.prompt([ { type: 'checkbox', name: 'fullIntegrationExamples', message: '🎯 Selecciona los ejemplos de integración completa que deseas incluir:', choices: AVAILABLE_EXAMPLES.map(example => ({ name: `${example.name} - ${example.description}`, value: example.value, checked: false })), validate: (answer) => { if (answer.length === 0) { return 'Debes seleccionar al menos un ejemplo o desmarcar la opción anterior.'; } return true; } } ]); Object.assign(fullIntegrationConfig, fullIntegrationExamples); } Object.assign(config, fullIntegrationConfig); // Configuraciones finales const finalConfig = await inquirer.prompt([ { type: 'confirm', name: 'envExample', message: '⚙️ ¿Deseas archivo .env.example con todas las variables configuradas?', default: true }, { type: 'confirm', name: 'documentation', message: '📖 ¿Deseas documentación completa (README.md y DOCUMENTACION.md)?', default: true } ]); Object.assign(config, finalConfig); return config; } program .name('sysrot-hub') .description('CLI de nueva generación para proyectos Next.js con IA, autenticación y más') .version('1.0.11') .argument('[project-name]', 'Nombre del proyecto') .option('-y, --yes', 'Usar configuración por defecto') .option('-v, --version', 'Mostrar versión') .option('--verbose', 'Mostrar logs detallados') .option('--skip-install', 'Saltar instalación de dependencias') .action(async (projectName, options) => { // Configurar modo verbose si está habilitado if (options.verbose) { process.env.SYSROT_VERBOSE = 'true'; } if (options.help) { showHelp(); return; } if (options.version) { logger.showVersion('1.0.11'); return; } if (options.examples) { console.log(chalk.blue('\n🎨 Available Full Integration Examples:\n')); AVAILABLE_EXAMPLES.forEach((example, index) => { console.log(chalk.cyan(`${index + 1}. ${example.name}`)); console.log(chalk.gray(` ${example.description}`)); console.log(''); }); return; } showLogo(); // Validar nombre del proyecto if (!projectName) { logger.info('Configurando tu proyecto...'); const { name } = await inquirer.prompt([ { type: 'input', name: 'name', message: '📝 Nombre del proyecto:', default: 'mi-proyecto-sysrot', validate: (input) => { if (!input || input.trim().length === 0) { return 'El nombre del proyecto es requerido'; } if (!/^[a-zA-Z0-9-_]+$/.test(input)) { return 'El nombre solo puede contener letras, números, guiones y guiones bajos'; } if (input.length > 50) { return 'El nombre debe tener menos de 50 caracteres'; } return true; } } ]); projectName = name.trim(); } // Validar que el nombre del proyecto es válido if (!/^[a-zA-Z0-9-_]+$/.test(projectName)) { logger.error('Nombre de proyecto inválido. Solo se permiten letras, números, guiones y guiones bajos.'); process.exit(1); } // Configuración interactiva completa const config = await askProjectConfiguration(); config.projectName = projectName; // Mostrar resumen de configuración logger.showConfigSummary(config); // Confirmación final const { proceed } = await inquirer.prompt([ { type: 'confirm', name: 'proceed', message: '✅ ¿Deseas continuar con esta configuración?', default: true } ]); if (!proceed) { logger.info('Operación cancelada por el usuario.'); process.exit(0); } logger.projectStart(projectName); try { logger.debug('Configuración del proyecto:', config); await createProject(config); logger.projectSuccess(projectName); // Show information about selected examples if (config.fullIntegrationExamples && config.fullIntegrationExamples.length > 0) { console.log(chalk.green('\n✨ Ejemplos de integración completa incluidos:')); config.fullIntegrationExamples.forEach(exampleValue => { const example = AVAILABLE_EXAMPLES.find(e => e.value === exampleValue); console.log(chalk.cyan(` • ${example.name}`)); }); console.log(chalk.yellow('\n📚 Revisa la documentación en /pages/ejemplos/ para más detalles')); } } catch (error) { logger.handleError(error, 'crear el proyecto'); process.exit(1); } }); program.parse(process.argv); // Si no se proporcionan argumentos, mostrar ayuda if (!process.argv.slice(2).length) { showLogo(); showHelp(); }