UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

128 lines 7 kB
"use strict"; /** * AI-Enhanced Watch Command * * This command provides an intelligent file watching capability that automatically * generates tests, performs security analysis, and creates QA checklists as you code. * It's designed to work seamlessly with code generation tools like Cursor AI. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.watchAICommand = watchAICommand; const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const path_1 = __importDefault(require("path")); // Use a compatible way to import figures const figures = { tick: '✓', cross: '✖', warning: '⚠', info: 'ℹ', pointer: '❯', line: '│' }; const enhancedWatcher_1 = require("../core/enhancedWatcher"); function watchAICommand(program) { program .command('watch-ai') .description('Watch files and automatically generate tests, security reports, and checklists as you code') .argument('[directory]', 'Directory to watch', '.') .option('-t, --tests', 'Generate tests on file changes', true) .option('-s, --security', 'Perform security analysis on file changes', true) .option('-c, --checklists', 'Generate QA checklists on file changes', true) .option('-a, --ai', 'Use AI-enhanced security analysis', false) .option('--test-output <dir>', 'Output directory for tests', './tests') .option('--security-output <dir>', 'Output directory for security reports', './security-reports') .option('--checklist-output <dir>', 'Output directory for checklists', './checklists') .option('--include <patterns...>', 'Glob patterns to include') .option('--exclude <patterns...>', 'Glob patterns to exclude') .option('--concurrent <n>', 'Maximum concurrent tasks', '3') .option('--silent', 'Run in silent mode (no progress reporting)', false) .option('--test-format <format>', 'Test format (playwright or selenium)', 'playwright') .action(async (directory, options) => { // Normalize directory path const dirPath = path_1.default.resolve(process.cwd(), directory); // Display banner console.log(chalk_1.default.cyan.bold('\n┌──────────────────────────────────────────────┐')); console.log(chalk_1.default.cyan.bold('│ ctrl.shift.left AI-Enhanced Watcher │')); console.log(chalk_1.default.cyan.bold('└──────────────────────────────────────────────┘')); console.log(chalk_1.default.dim(`Version 1.0.0 | Mode: ${options.ai ? 'AI-Enhanced' : 'Standard'}\n`)); // Check for OpenAI API key if AI mode is enabled if (options.ai && !process.env.OPENAI_API_KEY) { console.log(chalk_1.default.yellow(`${figures.warning} AI-enhanced security analysis requested, but no OpenAI API key found.`)); console.log(chalk_1.default.yellow(`${figures.line} Set the OPENAI_API_KEY environment variable to enable AI features.`)); console.log(chalk_1.default.yellow(`${figures.line} Falling back to pattern-based analysis.\n`)); } // Create watcher options const watcherOptions = { include: options.include, exclude: options.exclude, generateTests: options.tests, analyzeSecurity: options.security, useAIAnalysis: options.ai, generateChecklists: options.checklists, testOutputDir: options.testOutput, securityOutputDir: options.securityOutput, checklistOutputDir: options.checklistOutput, maxConcurrentTasks: parseInt(options.concurrent, 10), reportProgress: !options.silent, testFormat: options.testFormat, openAIApiKey: process.env.OPENAI_API_KEY }; // Create and start the watcher const watcher = new enhancedWatcher_1.EnhancedWatcher(watcherOptions); // Setup event handlers for real-time feedback watcher.on('ready', () => { console.log(chalk_1.default.green(`${figures.tick} Watcher ready and monitoring ${chalk_1.default.cyan(dirPath)}`)); console.log(chalk_1.default.green(`${figures.line} AI Integration: ${options.ai ? (process.env.OPENAI_API_KEY ? 'Active' : 'Disabled (no API key)') : 'Disabled'}`)); console.log(chalk_1.default.green(`${figures.line} Press Ctrl+C to stop the watcher\n`)); }); watcher.on('file:change', (event) => { if (!options.silent) { console.log(chalk_1.default.blue(`${figures.pointer} File ${event.type}: ${path_1.default.basename(event.path)}`)); } }); watcher.on('analysis:complete', (result) => { if (!options.silent && result.success) { const typeColor = result.type === 'test' ? chalk_1.default.magenta : result.type === 'security' ? chalk_1.default.yellow : chalk_1.default.blue; console.log(`${chalk_1.default.green(figures.tick)} ${typeColor(result.type.toUpperCase())} analysis complete for ${path_1.default.basename(result.filePath)} (${result.duration}ms)`); if (result.outputPath) { console.log(`${chalk_1.default.dim(figures.line)} Output: ${result.outputPath}`); } } }); watcher.on('error', (error) => { console.error(chalk_1.default.red(`${figures.cross} Error: ${error.message}`)); }); // Start watching const stopWatching = watcher.watch(dirPath); // Handle process exit const handleExit = async () => { console.log(chalk_1.default.yellow('\n\nStopping watcher...')); const spinner = (0, ora_1.default)('Cleaning up...').start(); await watcher.stop(); spinner.succeed('Watcher stopped'); console.log(chalk_1.default.green(`\n${figures.tick} Thank you for using ctrl.shift.left!`)); process.exit(0); }; // Handle interrupts process.on('SIGINT', handleExit); process.on('SIGTERM', handleExit); try { // Keep the process running await new Promise(() => { }); // Never resolves } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(chalk_1.default.red(`${figures.cross} Error: ${errorMessage}`)); await watcher.stop(); process.exit(1); } }); } exports.default = watchAICommand; //# sourceMappingURL=watch-ai.js.map