UNPKG

prprompts-flutter-generator

Version:

AI-powered Flutter development with full automation + official extension support - Generate 32 security-audited guides & auto-implement in 2-3 hours. NEW v5.1: Official Claude Code plugin with hooks, Gemini TOML commands, Qwen MCP settings. Features: Comp

670 lines (579 loc) • 19.5 kB
#!/usr/bin/env node /** * Interactive Mode for PRPROMPTS Flutter Generator * Provides a menu-driven interface for easier command selection * @version 4.1.0 */ const readline = require('readline'); const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); class InteractiveMode { constructor() { this.rl = null; this.currentMenu = 'main'; this.history = []; this.config = this.loadConfig(); // Menu structure this.menus = { main: { title: 'šŸš€ PRPROMPTS Flutter Generator - Interactive Mode', options: [ { key: '1', label: 'Create PRD (Product Requirements)', action: 'create_prd' }, { key: '2', label: 'Generate PRPROMPTS', action: 'generate_prprompts' }, { key: '3', label: 'Automation Pipeline', action: 'menu:automation' }, { key: '4', label: 'AI Configuration', action: 'menu:ai_config' }, { key: '5', label: 'Project Tools', action: 'menu:tools' }, { key: '6', label: 'Settings', action: 'menu:settings' }, { key: '7', label: 'Help & Documentation', action: 'menu:help' }, { key: 'q', label: 'Exit', action: 'exit' } ] }, automation: { title: 'šŸ¤– Automation Pipeline', options: [ { key: '1', label: 'Bootstrap Project', action: 'auto_bootstrap' }, { key: '2', label: 'Implement Features', action: 'auto_implement' }, { key: '3', label: 'Run Full Cycle', action: 'auto_full_cycle' }, { key: '4', label: 'Run Tests', action: 'auto_test' }, { key: '5', label: 'Validate Code', action: 'auto_validate' }, { key: '6', label: 'Check Status', action: 'auto_status' }, { key: '7', label: 'Reset State', action: 'auto_reset' }, { key: 'b', label: 'Back', action: 'menu:main' } ] }, ai_config: { title: 'šŸ”§ AI Configuration', options: [ { key: '1', label: 'Setup API Keys', action: 'setup_api_keys' }, { key: '2', label: 'Validate API Keys', action: 'validate_api_keys' }, { key: '3', label: 'Check Rate Limits', action: 'check_rate_limits' }, { key: '4', label: 'Set AI Tier', action: 'set_ai_tier' }, { key: '5', label: 'Select Default AI', action: 'select_default_ai' }, { key: '6', label: 'Test AI Connection', action: 'test_ai_connection' }, { key: 'b', label: 'Back', action: 'menu:main' } ] }, tools: { title: 'šŸ› ļø Project Tools', options: [ { key: '1', label: 'Analyze PRD', action: 'analyze_prd' }, { key: '2', label: 'From Files (Convert existing docs)', action: 'from_files' }, { key: '3', label: 'Update PRPROMPTS', action: 'update_prprompts' }, { key: '4', label: 'Review Implementation', action: 'review_implementation' }, { key: '5', label: 'QA Check', action: 'qa_check' }, { key: '6', label: 'Export Project', action: 'export_project' }, { key: 'b', label: 'Back', action: 'menu:main' } ] }, settings: { title: 'āš™ļø Settings', options: [ { key: '1', label: 'Configure Environment Variables', action: 'config_env' }, { key: '2', label: 'Update Package', action: 'update_package' }, { key: '3', label: 'View Configuration', action: 'view_config' }, { key: '4', label: 'Clear Cache', action: 'clear_cache' }, { key: '5', label: 'Run Diagnostics', action: 'run_diagnostics' }, { key: 'b', label: 'Back', action: 'menu:main' } ] }, help: { title: 'ā“ Help & Documentation', options: [ { key: '1', label: 'Quick Start Guide', action: 'show_quickstart' }, { key: '2', label: 'View README', action: 'show_readme' }, { key: '3', label: 'Architecture Guide', action: 'show_architecture' }, { key: '4', label: 'Troubleshooting', action: 'show_troubleshooting' }, { key: '5', label: 'Command Reference', action: 'show_commands' }, { key: '6', label: 'Examples', action: 'show_examples' }, { key: 'b', label: 'Back', action: 'menu:main' } ] } }; // Command mapping this.commands = { create_prd: 'prprompts create', generate_prprompts: 'prprompts generate', auto_bootstrap: 'prprompts auto-bootstrap', auto_implement: 'prprompts auto-implement', auto_full_cycle: this.getAICommand('full-cycle'), auto_test: 'prprompts auto-test', auto_validate: 'prprompts auto-validate', auto_status: 'prprompts auto-status', auto_reset: 'prprompts auto-reset', analyze_prd: 'prprompts analyze', from_files: 'prprompts from-files', update_prprompts: 'prprompts update', review_implementation: this.getAICommand('review-and-commit'), qa_check: this.getAICommand('qa-check'), run_diagnostics: 'prprompts doctor' }; } /** * Load configuration */ loadConfig() { const configPath = path.join( process.env.HOME || process.env.USERPROFILE, '.prprompts', 'config.json' ); try { if (fs.existsSync(configPath)) { return JSON.parse(fs.readFileSync(configPath, 'utf8')); } } catch (error) { // Use defaults } return { defaultAI: 'claude', verbose: false }; } /** * Get AI-specific command */ getAICommand(command) { const ai = this.config.defaultAI || 'claude'; return `${ai} ${command}`; } /** * Start interactive mode */ async start() { console.clear(); this.displayWelcome(); this.rl = readline.createInterface({ input: process.stdin, output: process.stdout }); await this.displayMenu(); } /** * Display welcome message */ displayWelcome() { console.log(` ╔════════════════════════════════════════════════════════════╗ ā•‘ ā•‘ ā•‘ PRPROMPTS Flutter Generator - Interactive Mode ā•‘ ā•‘ Version 4.1.0 ā•‘ ā•‘ ā•‘ ā•‘ Generate production-ready Flutter apps 40-60x faster ā•‘ ā•‘ ā•‘ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā• `); } /** * Display current menu */ async displayMenu() { const menu = this.menus[this.currentMenu]; if (!menu) { console.error('Invalid menu'); this.currentMenu = 'main'; return this.displayMenu(); } console.log(`\n${menu.title}`); console.log('─'.repeat(60)); for (const option of menu.options) { const label = option.key.length === 1 ? ` ${option.key}.` : `${option.key}.`; console.log(`${label} ${option.label}`); } console.log('─'.repeat(60)); this.prompt(); } /** * Show prompt and handle input */ prompt() { this.rl.question('\n> Select an option: ', async (input) => { await this.handleInput(input.trim().toLowerCase()); }); } /** * Handle user input */ async handleInput(input) { const menu = this.menus[this.currentMenu]; const option = menu.options.find(o => o.key === input); if (!option) { console.log('\nāŒ Invalid option. Please try again.'); await this.displayMenu(); return; } this.history.push({ menu: this.currentMenu, option: option.label }); // Handle action if (option.action === 'exit') { await this.exit(); } else if (option.action.startsWith('menu:')) { this.currentMenu = option.action.replace('menu:', ''); console.clear(); await this.displayMenu(); } else { await this.executeAction(option.action); } } /** * Execute an action */ async executeAction(action) { console.log(''); switch (action) { case 'setup_api_keys': await this.setupAPIKeys(); break; case 'validate_api_keys': await this.validateAPIKeys(); break; case 'check_rate_limits': await this.checkRateLimits(); break; case 'set_ai_tier': await this.setAITier(); break; case 'select_default_ai': await this.selectDefaultAI(); break; case 'test_ai_connection': await this.testAIConnection(); break; case 'config_env': await this.configureEnvironment(); break; case 'update_package': await this.updatePackage(); break; case 'view_config': await this.viewConfiguration(); break; case 'clear_cache': await this.clearCache(); break; case 'export_project': await this.exportProject(); break; case 'show_quickstart': await this.showDocumentation('WINDOWS-QUICKSTART.md'); break; case 'show_readme': await this.showDocumentation('README.md'); break; case 'show_architecture': await this.showDocumentation('ARCHITECTURE.md'); break; case 'show_troubleshooting': await this.showDocumentation('docs/TROUBLESHOOTING.md'); break; case 'show_commands': await this.showCommands(); break; case 'show_examples': await this.showExamples(); break; case 'auto_implement': await this.autoImplementWithPrompt(); break; default: // Execute command const command = this.commands[action]; if (command) { await this.executeCommand(command); } else { console.log(`āŒ Action '${action}' not implemented`); } } // Return to menu if (this.rl) { console.log('\nPress Enter to continue...'); await new Promise(resolve => { this.rl.once('line', resolve); }); console.clear(); await this.displayMenu(); } } /** * Execute a shell command */ async executeCommand(command) { console.log(`\nšŸš€ Executing: ${command}\n`); try { execSync(command, { stdio: 'inherit' }); console.log('\nāœ… Command completed successfully'); } catch (error) { console.error(`\nāŒ Command failed: ${error.message}`); } } /** * Setup API keys interactively */ async setupAPIKeys() { const APIKeyValidator = require('./api-key-validator'); const validator = new APIKeyValidator(); console.log('\nšŸ”‘ API Key Setup\n'); const ais = ['claude', 'qwen', 'gemini']; for (const ai of ais) { const existing = validator.findAPIKey(ai); if (existing) { console.log(`āœ“ ${ai}: Already configured`); } else { const answer = await this.askQuestion(`Setup ${ai} API key? (y/n): `); if (answer.toLowerCase() === 'y') { await validator.setupAPIKey(ai); } } } } /** * Validate API keys */ async validateAPIKeys() { console.log('\nšŸ” Validating API Keys...\n'); try { execSync('node lib/api-key-validator.js validate', { stdio: 'inherit' }); } catch (error) { console.error('Validation failed:', error.message); } } /** * Check rate limits */ async checkRateLimits() { console.log('\nšŸ“Š Rate Limit Status\n'); try { execSync('node lib/rate-limiter.js status', { stdio: 'inherit' }); } catch (error) { console.error('Failed to check rate limits:', error.message); } } /** * Set AI tier */ async setAITier() { const ai = await this.askQuestion('AI (claude/qwen/gemini): '); const tier = await this.askQuestion('Tier (free/pro/starter): '); try { execSync(`node lib/rate-limiter.js tier ${ai} ${tier}`, { stdio: 'inherit' }); } catch (error) { console.error('Failed to set tier:', error.message); } } /** * Select default AI */ async selectDefaultAI() { console.log('\nšŸ¤– Select Default AI\n'); console.log('1. Claude'); console.log('2. Qwen'); console.log('3. Gemini'); const choice = await this.askQuestion('\nSelect (1-3): '); const ais = ['claude', 'qwen', 'gemini']; const selected = ais[parseInt(choice) - 1]; if (selected) { this.config.defaultAI = selected; this.saveConfig(); console.log(`\nāœ… Default AI set to ${selected}`); } else { console.log('\nāŒ Invalid selection'); } } /** * Test AI connection */ async testAIConnection() { const ai = this.config.defaultAI || 'claude'; console.log(`\nšŸ”Œ Testing ${ai} connection...\n`); try { execSync(`${ai} --version`, { stdio: 'inherit' }); console.log(`\nāœ… ${ai} is working correctly`); } catch (error) { console.error(`\nāŒ ${ai} connection failed`); } } /** * Configure environment variables */ async configureEnvironment() { console.log('\nāš™ļø Environment Variables\n'); const vars = [ { name: 'PRPROMPTS_DEFAULT_AI', desc: 'Default AI', current: process.env.PRPROMPTS_DEFAULT_AI }, { name: 'PRPROMPTS_VERBOSE', desc: 'Verbose output', current: process.env.PRPROMPTS_VERBOSE }, { name: 'PRPROMPTS_TIMEOUT', desc: 'Command timeout', current: process.env.PRPROMPTS_TIMEOUT }, { name: 'PRPROMPTS_RETRY_COUNT', desc: 'Retry count', current: process.env.PRPROMPTS_RETRY_COUNT } ]; for (const v of vars) { console.log(`${v.name}:`); console.log(` Description: ${v.desc}`); console.log(` Current: ${v.current || '(not set)'}`); console.log(''); } console.log('To set variables, use:'); console.log(' Windows: set VARIABLE_NAME=value'); console.log(' Linux/Mac: export VARIABLE_NAME=value'); } /** * Update package */ async updatePackage() { console.log('\nšŸ“¦ Checking for updates...\n'); try { execSync('npm update -g prprompts-flutter-generator', { stdio: 'inherit' }); } catch (error) { console.error('Update failed:', error.message); } } /** * View configuration */ async viewConfiguration() { console.log('\nšŸ“‹ Current Configuration\n'); console.log(JSON.stringify(this.config, null, 2)); } /** * Clear cache */ async clearCache() { const cacheDir = path.join( process.env.HOME || process.env.USERPROFILE, '.prprompts', 'cache' ); try { if (fs.existsSync(cacheDir)) { fs.rmSync(cacheDir, { recursive: true }); console.log('āœ… Cache cleared'); } else { console.log('No cache to clear'); } } catch (error) { console.error('Failed to clear cache:', error.message); } } /** * Export project */ async exportProject() { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const exportFile = `prprompts-export-${timestamp}.tar.gz`; console.log(`\nšŸ“¦ Exporting project to ${exportFile}...\n`); try { execSync(`tar -czf ${exportFile} docs/ PRPROMPTS/ .prprompts/`, { stdio: 'inherit' }); console.log(`\nāœ… Project exported to ${exportFile}`); } catch (error) { console.error('Export failed:', error.message); } } /** * Show documentation */ async showDocumentation(file) { const docPath = path.join(__dirname, '..', file); try { const content = fs.readFileSync(docPath, 'utf8'); const lines = content.split('\n').slice(0, 50); console.log(lines.join('\n')); console.log('\n... (truncated, view full file for complete documentation)'); } catch (error) { console.error(`Failed to read ${file}:`, error.message); } } /** * Show commands */ async showCommands() { console.log('\nšŸ“œ Command Reference\n'); const commands = [ ['prprompts create', 'Create a PRD interactively'], ['prprompts generate', 'Generate PRPROMPTS files'], ['prprompts auto-bootstrap', 'Bootstrap project structure'], ['prprompts auto-implement N', 'Implement N features'], ['prprompts auto-test', 'Run tests with coverage'], ['prprompts auto-validate', 'Validate code quality'], ['prprompts auto-status', 'Show automation progress'], ['prprompts doctor', 'Run diagnostics'] ]; for (const [cmd, desc] of commands) { console.log(` ${cmd.padEnd(30)} ${desc}`); } } /** * Show examples */ async showExamples() { console.log('\nšŸ“š Examples\n'); const examples = [ 'Healthcare App', 'E-commerce Platform', 'Fintech Solution', 'Social Media App', 'Educational Platform' ]; console.log('Available example projects:\n'); for (const example of examples) { console.log(` • ${example}`); } console.log('\nView examples in: examples/ directory'); } /** * Auto implement with prompt for number */ async autoImplementWithPrompt() { const num = await this.askQuestion('Number of features to implement (1-10): '); const n = parseInt(num); if (n >= 1 && n <= 10) { await this.executeCommand(`prprompts auto-implement ${n}`); } else { console.log('āŒ Please enter a number between 1 and 10'); } } /** * Ask a question */ async askQuestion(question) { return new Promise(resolve => { this.rl.question(question, resolve); }); } /** * Save configuration */ saveConfig() { const configPath = path.join( process.env.HOME || process.env.USERPROFILE, '.prprompts', 'config.json' ); try { const dir = path.dirname(configPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(configPath, JSON.stringify(this.config, null, 2)); } catch (error) { console.error('Failed to save config:', error.message); } } /** * Exit interactive mode */ async exit() { console.log('\nšŸ‘‹ Thank you for using PRPROMPTS!\n'); if (this.history.length > 0) { console.log('Session Summary:'); this.history.slice(-5).forEach(h => { console.log(` • ${h.option}`); }); } this.rl.close(); process.exit(0); } } // CLI Interface if (require.main === module) { const interactive = new InteractiveMode(); interactive.start().catch(console.error); } module.exports = InteractiveMode;