ctrlshiftleft
Version:
AI-powered toolkit for embedding QA and security testing into development workflows
156 lines (135 loc) • 4.06 kB
JavaScript
/**
* ctrl.shift.left CLI
* Unified command-line interface for security analysis, test generation, and QA checklists
*/
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
// Configuration
const TOOLS_DIR = __dirname;
// Command definitions
const COMMANDS = {
'analyze': {
script: path.join(TOOLS_DIR, 'analyze-security.js'),
description: 'Analyze a file for security vulnerabilities',
usage: 'analyze <file-path>',
examples: [
'analyze src/components/LoginForm.js',
'analyze src/utils/validation.ts'
]
},
'gen': {
script: path.join(TOOLS_DIR, 'generate-tests.js'),
description: 'Generate Playwright tests for a component',
usage: 'gen <file-path> [output-dir]',
examples: [
'gen src/components/PaymentForm.tsx',
'gen src/components/Form.js tests/e2e'
]
},
'checklist': {
script: path.join(TOOLS_DIR, 'generate-checklist.js'),
description: 'Create a QA and security checklist for a component',
usage: 'checklist <file-path> [output-file]',
examples: [
'checklist src/components/PaymentForm.tsx',
'checklist src/App.js qa/app-checklist.json'
]
},
'run': {
description: 'Run generated tests (shortcut to npx playwright test)',
usage: 'run [test-file-or-dir]',
examples: [
'run',
'run generated-tests/LoginForm.spec.ts'
]
},
'watch': {
description: 'Watch files and run security analysis on changes',
usage: 'watch <directory> [--exclude=pattern]',
examples: [
'watch src/components',
'watch src --exclude=node_modules'
]
}
};
/**
* Display help information
*/
function showHelp(command) {
console.log('\x1b[36m%s\x1b[0m', '🛡️ ctrl.shift.left - Shift Security & QA Left');
console.log('\x1b[36m%s\x1b[0m', '==========================================');
if (command && COMMANDS[command]) {
const cmd = COMMANDS[command];
console.log(`\n\x1b[33m${command}\x1b[0m: ${cmd.description}`);
console.log(`\nUsage: \x1b[32mctrlshiftleft ${cmd.usage}\x1b[0m`);
console.log('\nExamples:');
cmd.examples.forEach(example => {
console.log(` ctrlshiftleft ${example}`);
});
} else {
console.log('\nAvailable commands:');
Object.keys(COMMANDS).forEach(cmd => {
console.log(` \x1b[33m${cmd.padEnd(10)}\x1b[0m ${COMMANDS[cmd].description}`);
});
console.log('\nFor help with a specific command:');
console.log(' ctrlshiftleft help <command>');
}
}
/**
* Execute a command with arguments
*/
function executeCommand(command, args) {
if (command === 'help') {
showHelp(args[0]);
return;
}
if (command === 'run') {
console.log('Running tests...');
const testArgs = ['playwright', 'test'].concat(args);
const proc = spawn('npx', testArgs, { stdio: 'inherit' });
proc.on('close', (code) => {
if (code !== 0) {
console.error(`Tests exited with code ${code}`);
}
});
return;
}
if (command === 'watch') {
console.log('Watch mode is not implemented in this demo version');
console.log('Use the analyze command to analyze files on demand');
return;
}
const cmdConfig = COMMANDS[command];
if (!cmdConfig || !cmdConfig.script) {
console.error(`Unknown command: ${command}`);
showHelp();
return;
}
// Execute the appropriate script
const scriptPath = cmdConfig.script;
if (!fs.existsSync(scriptPath)) {
console.error(`Error: Script not found: ${scriptPath}`);
return;
}
const proc = spawn('node', [scriptPath].concat(args), { stdio: 'inherit' });
proc.on('close', (code) => {
if (code !== 0) {
console.error(`Command exited with code ${code}`);
}
});
}
/**
* Main function
*/
function main() {
const [,, command, ...args] = process.argv;
if (!command || command === '--help' || command === '-h') {
showHelp();
return;
}
executeCommand(command, args);
}
// Run the CLI
main();