UNPKG

kira-crud

Version:

Intelligent CRUD Generator for Laravel and Angular

240 lines (205 loc) 6.7 kB
#!/usr/bin/env node /** * Custom Generator CLI * Generates Angular components following the project structure */ const chalk = require('chalk'); const ora = require('ora'); const figlet = require('figlet'); const boxen = require('boxen'); const path = require('path'); const fs = require('fs').promises; const inquirer = require('inquirer'); const { program } = require('commander'); const gradient = require('gradient-string'); const yaml = require('js-yaml'); const AngularCustomGenerator = require('./generators/angular-custom-generator'); const { validateConfigFile, displayValidationResults } = require('./utils/config-validator'); // Constants for styling const titleGradient = gradient(['#4285F4', '#34A853']); /** * Display the banner */ function displayBanner() { console.log( titleGradient.multiline( figlet.textSync('Kira Custom', { font: 'Small', horizontalLayout: 'default' }) ) ); console.log( boxen( `${chalk.bold('KIRA Custom Generator')} ${chalk.dim('v1.0.0')}\n` + `Generate Angular components that match your project structure`, { padding: 1, margin: { top: 1, bottom: 1 }, borderStyle: 'round', borderColor: 'green' } ) ); } /** * Find configuration files in a directory * @param {string} directory - Directory to search * @returns {Promise<Array>} - List of configuration files */ async function findConfigFiles(directory) { try { const files = await fs.readdir(directory); return files.filter(file => file.endsWith('.yml') || file.endsWith('.yaml') || file.endsWith('.json') ); } catch (error) { console.error(chalk.red(`Error reading directory: ${error.message}`)); return []; } } /** * Generate custom components from a configuration file * @param {string} configPath - Path to the configuration file * @param {Object} options - Generation options */ async function generateFromConfig(configPath, options) { const spinner = ora('Loading configuration...').start(); try { // Validate configuration const validationResult = await validateConfigFile(configPath); if (!validationResult.valid) { spinner.fail('Configuration validation failed'); displayValidationResults(validationResult); return; } spinner.succeed('Configuration validated successfully'); // Create generator const generator = new AngularCustomGenerator({ outputPath: options.output || 'front/src/app/pages/admin/settings', verbose: options.verbose }); // Load configuration await generator.loadConfig(configPath); await generator.initialize(); // Execute generation spinner.text = 'Generating components...'; spinner.start(); const success = await generator.execute(); if (success) { spinner.succeed('Components generated successfully'); // Display summary const summary = generator.transaction.getSummary(); console.log(boxen( `${chalk.green.bold('✓')} Generated ${chalk.cyan(generator.config.model.name)} components\n\n` + `${chalk.bold('Files created/modified:')} ${summary.operationsByType.write || 0}\n` + `${chalk.bold('Directories created:')} ${summary.operationsByType.mkdir || 0}\n\n` + `${chalk.gray('Output directory:')} ${path.join(options.output || 'front/src/app/pages/admin/settings', generator.modelData.kebabCase)}`, { padding: 1, margin: 1, borderStyle: 'round', borderColor: 'green' } )); } else { spinner.fail('Generation failed'); } } catch (error) { spinner.fail('Generation failed'); console.error(chalk.red(`\nError: ${error.message}`)); } } /** * Run the generator in interactive mode */ async function runInteractive() { displayBanner(); // Find configuration files // Chercher d'abord dans le répertoire du module (fonctionne avec npm global) // puis dans le répertoire du projet courant const globalExamplesDir = path.join(__dirname, 'examples'); const localExamplesDir = path.join(process.cwd(), 'examples'); let configFiles = await findConfigFiles(globalExamplesDir); // Si aucun fichier trouvé dans le répertoire global, essayer le répertoire local if (configFiles.length === 0) { configFiles = await findConfigFiles(localExamplesDir); } if (configFiles.length === 0) { console.log(chalk.yellow('No configuration files found in examples directory.')); return; } // Déterminer le bon répertoire source pour les fichiers de configuration // Cela permet de gérer aussi bien les installations globales que locales let usedExamplesDir; try { await fs.access(path.join(globalExamplesDir, configFiles[0])); usedExamplesDir = globalExamplesDir; } catch (error) { usedExamplesDir = localExamplesDir; } const { configFile } = await inquirer.prompt({ type: 'list', name: 'configFile', message: 'Select a configuration file:', choices: configFiles.map(file => ({ name: file, value: path.join(usedExamplesDir, file) })) }); const { outputPath } = await inquirer.prompt({ type: 'input', name: 'outputPath', message: 'Output directory for components:', default: 'front/src/app/pages/admin/settings' }); const { verbose } = await inquirer.prompt({ type: 'confirm', name: 'verbose', message: 'Enable verbose output?', default: false }); await generateFromConfig(configFile, { output: outputPath, verbose }); } /** * Command line interface setup */ program .version('1.0.0') .description('KIRA Custom Generator') .option('-c, --config <path>', 'Path to configuration file') .option('-o, --output <path>', 'Output directory for components') .option('-v, --verbose', 'Enable verbose output') .option('-i, --interactive', 'Run in interactive mode'); program.parse(process.argv); /** * Main application entry point */ async function main() { const options = program.opts(); // Default to interactive mode if no config provided if (!options.config && !options.interactive) { options.interactive = true; } try { if (options.interactive) { await runInteractive(); } else if (options.config) { displayBanner(); await generateFromConfig(options.config, options); } } catch (error) { console.error(chalk.red(`\nAn error occurred: ${error.message}\n`)); process.exit(1); } } // Run the application if (require.main === module) { main(); } module.exports = { generateFromConfig };