diff --git a/scripts/modules/commands.js b/scripts/modules/commands.js index d0c529db..5fbf6327 100644 --- a/scripts/modules/commands.js +++ b/scripts/modules/commands.js @@ -41,7 +41,8 @@ import { displayNextTask, displayTaskById, displayComplexityReport, - getStatusWithColor + getStatusWithColor, + confirmTaskOverwrite } from './ui.js'; /** @@ -70,17 +71,34 @@ function registerCommands(programInstance) { .option('-i, --input ', 'Path to the PRD file (alternative to positional argument)') .option('-o, --output ', 'Output file path', 'tasks/tasks.json') .option('-n, --num-tasks ', 'Number of tasks to generate', '10') + .option('-f, --force', 'Skip confirmation when overwriting existing tasks') .action(async (file, options) => { // Use input option if file argument not provided const inputFile = file || options.input; const defaultPrdPath = 'scripts/prd.txt'; + const numTasks = parseInt(options.numTasks, 10); + const outputPath = options.output; + const force = options.force || false; + + // Helper function to check if tasks.json exists and confirm overwrite + async function confirmOverwriteIfNeeded() { + if (fs.existsSync(outputPath) && !force) { + const shouldContinue = await confirmTaskOverwrite(outputPath); + if (!shouldContinue) { + console.log(chalk.yellow('Operation cancelled by user.')); + return false; + } + } + return true; + } // If no input file specified, check for default PRD location if (!inputFile) { if (fs.existsSync(defaultPrdPath)) { console.log(chalk.blue(`Using default PRD file: ${defaultPrdPath}`)); - const numTasks = parseInt(options.numTasks, 10); - const outputPath = options.output; + + // Check for existing tasks.json before proceeding + if (!await confirmOverwriteIfNeeded()) return; console.log(chalk.blue(`Generating ${numTasks} tasks...`)); await parsePRD(defaultPrdPath, outputPath, numTasks); @@ -95,10 +113,12 @@ function registerCommands(programInstance) { chalk.cyan('Options:') + '\n' + ' -i, --input Path to the PRD file (alternative to positional argument)\n' + ' -o, --output Output file path (default: "tasks/tasks.json")\n' + - ' -n, --num-tasks Number of tasks to generate (default: 10)\n\n' + + ' -n, --num-tasks Number of tasks to generate (default: 10)\n' + + ' -f, --force Skip confirmation when overwriting existing tasks\n\n' + chalk.cyan('Example:') + '\n' + ' task-master parse-prd requirements.txt --num-tasks 15\n' + - ' task-master parse-prd --input=requirements.txt\n\n' + + ' task-master parse-prd --input=requirements.txt\n' + + ' task-master parse-prd --force\n\n' + chalk.yellow('Note: This command will:') + '\n' + ' 1. Look for a PRD file at scripts/prd.txt by default\n' + ' 2. Use the file specified by --input or positional argument if provided\n' + @@ -108,8 +128,8 @@ function registerCommands(programInstance) { return; } - const numTasks = parseInt(options.numTasks, 10); - const outputPath = options.output; + // Check for existing tasks.json before proceeding with specified input file + if (!await confirmOverwriteIfNeeded()) return; console.log(chalk.blue(`Parsing PRD file: ${inputFile}`)); console.log(chalk.blue(`Generating ${numTasks} tasks...`)); diff --git a/scripts/modules/ui.js b/scripts/modules/ui.js index 728e56d8..ccfd0649 100644 --- a/scripts/modules/ui.js +++ b/scripts/modules/ui.js @@ -1061,6 +1061,33 @@ async function displayComplexityReport(reportPath) { )); } +/** + * Confirm overwriting existing tasks.json file + * @param {string} tasksPath - Path to the tasks.json file + * @returns {Promise} - Promise resolving to true if user confirms, false otherwise + */ +async function confirmTaskOverwrite(tasksPath) { + console.log(boxen( + chalk.yellow('It looks like you\'ve already generated tasks for this project.\n') + + chalk.yellow('Executing this command will overwrite any existing tasks.'), + { padding: 1, borderColor: 'yellow', borderStyle: 'round', margin: { top: 1 } } + )); + + // Use dynamic import to get the readline module + const readline = await import('readline'); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + const answer = await new Promise(resolve => { + rl.question(chalk.cyan('Are you sure you wish to continue? (y/N): '), resolve); + }); + rl.close(); + + return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes'; +} + // Export UI functions export { displayBanner, @@ -1074,4 +1101,5 @@ export { displayNextTask, displayTaskById, displayComplexityReport, + confirmTaskOverwrite }; \ No newline at end of file