UNPKG

@vladimirdukelic/revolutionary-ui-factory

Version:

Revolutionary UI Factory System v2 - Generate ANY UI component for ANY framework with 60-95% code reduction

364 lines (363 loc) • 14.9 kB
"use strict"; /** * Revolutionary UI Factory - Package Installer * Handles package installation, updates, and configuration */ 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.PackageInstaller = void 0; const child_process_1 = require("child_process"); const util_1 = require("util"); const fs = __importStar(require("fs/promises")); const path = __importStar(require("path")); const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const execAsync = (0, util_1.promisify)(child_process_1.exec); class PackageInstaller { options; projectPath; spinner; constructor(projectPath, options) { this.projectPath = projectPath; this.options = options; this.spinner = (0, ora_1.default)(); } /** * Install packages based on wizard results */ async install(wizardResult) { const result = { success: true, installedPackages: [], failedPackages: [], configFilesCreated: [], errors: [], warnings: [] }; console.log(chalk_1.default.bold.blue('\nšŸ“¦ Installing packages...\n')); // Install packages for (const command of wizardResult.installCommands) { const success = await this.runInstallCommand(command, result); if (!success && !this.options.force) { result.success = false; break; } } // Create config files if (!this.options.skipConfigFiles && result.success) { await this.createConfigFiles(wizardResult.configFiles, result); } // Run post-install tasks if (result.success) { await this.runPostInstallTasks(wizardResult, result); } return result; } /** * Run a single install command */ async runInstallCommand(command, result) { if (this.options.dryRun) { console.log(chalk_1.default.gray(`[DRY RUN] Would run: ${command}`)); return true; } this.spinner.start(chalk_1.default.cyan(`Running: ${command}`)); try { if (this.options.verbose) { // Use spawn for real-time output await this.runCommandWithOutput(command); } else { // Use exec for silent execution await execAsync(command, { cwd: this.projectPath }); } this.spinner.succeed(chalk_1.default.green(`āœ… ${command}`)); // Extract package names from command const packages = this.extractPackagesFromCommand(command); result.installedPackages.push(...packages); return true; } catch (error) { this.spinner.fail(chalk_1.default.red(`āŒ Failed: ${command}`)); result.errors.push(`Failed to run: ${command}\nError: ${error.message}`); const packages = this.extractPackagesFromCommand(command); result.failedPackages.push(...packages); // Check for common errors if (error.message.includes('peer dep')) { result.warnings.push('Peer dependency issues detected. You may need to use --legacy-peer-deps'); } return false; } } /** * Run command with real-time output */ runCommandWithOutput(command) { return new Promise((resolve, reject) => { const [cmd, ...args] = command.split(' '); const child = (0, child_process_1.spawn)(cmd, args, { cwd: this.projectPath, shell: true, stdio: 'inherit' }); child.on('close', (code) => { if (code === 0) { resolve(); } else { reject(new Error(`Command failed with exit code ${code}`)); } }); child.on('error', reject); }); } /** * Create configuration files */ async createConfigFiles(configFiles, result) { console.log(chalk_1.default.bold.blue('\nšŸ“ Creating configuration files...\n')); for (const file of configFiles) { const filePath = path.join(this.projectPath, file.filename); try { // Check if file already exists const exists = await this.fileExists(filePath); if (exists && !this.options.force) { const backupPath = `${filePath}.backup`; if (this.options.dryRun) { console.log(chalk_1.default.gray(`[DRY RUN] Would backup: ${file.filename} to ${path.basename(backupPath)}`)); } else { await fs.copyFile(filePath, backupPath); result.warnings.push(`Backed up existing ${file.filename} to ${path.basename(backupPath)}`); } } if (this.options.dryRun) { console.log(chalk_1.default.gray(`[DRY RUN] Would create: ${file.filename}`)); console.log(chalk_1.default.gray(`Content preview:\n${file.content.substring(0, 200)}...`)); } else { await fs.writeFile(filePath, file.content, 'utf-8'); result.configFilesCreated.push(file.filename); console.log(chalk_1.default.green(`āœ… Created ${file.filename} - ${file.description}`)); } } catch (error) { result.errors.push(`Failed to create ${file.filename}: ${error.message}`); console.log(chalk_1.default.red(`āŒ Failed to create ${file.filename}`)); } } } /** * Run post-install tasks */ async runPostInstallTasks(wizardResult, result) { console.log(chalk_1.default.bold.blue('\nšŸ”§ Running post-install tasks...\n')); // Update package.json scripts await this.updatePackageJsonScripts(wizardResult, result); // Create example components if (wizardResult.selections.uiLibraries.length > 0) { await this.createExampleComponents(wizardResult, result); } // Set up git hooks if needed if (wizardResult.selections.devTools.includes('eslint') || wizardResult.selections.devTools.includes('prettier')) { await this.setupGitHooks(result); } } /** * Update package.json scripts */ async updatePackageJsonScripts(wizardResult, result) { const packageJsonPath = path.join(this.projectPath, 'package.json'); try { const content = await fs.readFile(packageJsonPath, 'utf-8'); const packageJson = JSON.parse(content); const newScripts = {}; // Add TypeScript scripts if (wizardResult.selections.devTools.includes('typescript')) { newScripts['type-check'] = 'tsc --noEmit'; newScripts['type-check:watch'] = 'tsc --noEmit --watch'; } // Add linting scripts if (wizardResult.selections.devTools.includes('eslint')) { newScripts['lint'] = 'eslint . --ext .js,.jsx,.ts,.tsx'; newScripts['lint:fix'] = 'eslint . --ext .js,.jsx,.ts,.tsx --fix'; } // Add formatting scripts if (wizardResult.selections.devTools.includes('prettier')) { newScripts['format'] = 'prettier --write .'; newScripts['format:check'] = 'prettier --check .'; } // Add Revolutionary UI scripts newScripts['ui:generate'] = 'revolutionary-ui generate'; newScripts['ui:analyze'] = 'revolutionary-ui analyze'; newScripts['ui:setup'] = 'revolutionary-ui setup'; // Merge scripts packageJson.scripts = { ...packageJson.scripts, ...newScripts }; if (this.options.dryRun) { console.log(chalk_1.default.gray('[DRY RUN] Would add scripts to package.json:')); Object.entries(newScripts).forEach(([key, value]) => { console.log(chalk_1.default.gray(` ${key}: ${value}`)); }); } else { await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8'); console.log(chalk_1.default.green('āœ… Updated package.json scripts')); } } catch (error) { result.warnings.push(`Could not update package.json scripts: ${error.message}`); } } /** * Create example components */ async createExampleComponents(wizardResult, result) { const componentsDir = path.join(this.projectPath, 'src', 'components', 'examples'); if (this.options.dryRun) { console.log(chalk_1.default.gray(`[DRY RUN] Would create example components in ${componentsDir}`)); return; } try { await fs.mkdir(componentsDir, { recursive: true }); // Create a simple example component const exampleComponent = `import React from 'react' ${wizardResult.selections.uiLibraries.includes('@mui/material') ? "import { Button } from '@mui/material'" : ''} ${wizardResult.selections.uiLibraries.includes('antd') ? "import { Button } from 'antd'" : ''} ${wizardResult.selections.iconLibraries.includes('lucide-react') ? "import { Sparkles } from 'lucide-react'" : ''} export const ExampleComponent = () => { return ( <div className="p-4"> <h2 className="text-2xl font-bold mb-4"> Welcome to Revolutionary UI Factory! ${wizardResult.selections.iconLibraries.includes('lucide-react') ? '<Sparkles className="inline w-6 h-6 ml-2" />' : ''} </h2> <p className="mb-4"> You've successfully set up your project with Revolutionary UI Factory. Start building amazing components with 60-95% less code! </p> ${wizardResult.selections.uiLibraries.length > 0 ? '<Button variant="contained" color="primary">Get Started</Button>' : '<button className="px-4 py-2 bg-blue-500 text-white rounded">Get Started</button>'} </div> ) } `; await fs.writeFile(path.join(componentsDir, 'ExampleComponent.tsx'), exampleComponent, 'utf-8'); console.log(chalk_1.default.green('āœ… Created example components')); } catch (error) { result.warnings.push(`Could not create example components: ${error.message}`); } } /** * Set up git hooks */ async setupGitHooks(result) { if (this.options.dryRun) { console.log(chalk_1.default.gray('[DRY RUN] Would set up git hooks for linting and formatting')); return; } try { // Check if husky is installed const huskyInstalled = await this.isPackageInstalled('husky'); if (!huskyInstalled) { console.log(chalk_1.default.yellow('ā„¹ļø Consider installing husky for git hooks:')); console.log(chalk_1.default.gray(` ${this.options.packageManager} ${this.options.packageManager === 'npm' ? 'install' : 'add'} -D husky lint-staged`)); console.log(chalk_1.default.gray(' npx husky install')); } } catch (error) { // Git hooks are optional, so just log a warning result.warnings.push('Could not set up git hooks'); } } // Helper methods async fileExists(filePath) { try { await fs.access(filePath); return true; } catch { return false; } } async isPackageInstalled(packageName) { try { const packageJsonPath = path.join(this.projectPath, 'package.json'); const content = await fs.readFile(packageJsonPath, 'utf-8'); const packageJson = JSON.parse(content); return (packageName in (packageJson.dependencies || {}) || packageName in (packageJson.devDependencies || {})); } catch { return false; } } extractPackagesFromCommand(command) { // Remove the package manager command and flags const parts = command.split(' '); const packages = []; let skipNext = false; for (let i = 1; i < parts.length; i++) { const part = parts[i]; if (skipNext) { skipNext = false; continue; } if (part.startsWith('-')) { // Skip flags and their values if (part === '-D' || part === '--save-dev') continue; if (part === '-g' || part === '--global') continue; skipNext = true; continue; } if (part === 'install' || part === 'add') continue; packages.push(part); } return packages; } } exports.PackageInstaller = PackageInstaller; //# sourceMappingURL=package-installer.js.map