UNPKG

hackages

Version:

CLI tool for learning software development concepts through test-driven development

122 lines (121 loc) • 5.86 kB
import { reviewCode } from "../services/claude.service.js"; import { displayFeedback, getAllSourceFiles, saveFeedbackToMarkdown, saveFeedbackToTemplate, generateFeedbackHTML, openFeedbackHTML, getLearningInformation, createNextExercise, } from "../services/file-manager.js"; import { printError, printHeader, printSuccess } from "../utils/console.js"; import chalk from "chalk"; import prompts from "prompts"; /** * Prompts user to select next learning step * @param suggestions Array of learning suggestions * @returns Selected option or custom learning goal */ async function promptNextLearningStep(suggestions) { console.log("\n" + chalk.cyan("=".repeat(50))); console.log(chalk.bold.yellow("šŸš€ Continue Your Learning Journey")); console.log(chalk.cyan("=".repeat(50))); console.log(chalk.gray("Choose your next learning step:\n")); let index = 0; const choices = [ ...suggestions.map((suggestion) => ({ title: `${++index}. ${suggestion.title}`, description: suggestion.description, value: suggestion.title + " - " + suggestion.description })), { title: `${++index}. Write your next learning goal`, description: "Take control of your next learning challenge...", value: "custom" } ]; const response = await prompts({ type: "select", name: "nextStep", message: "Select your next learning step:", choices, initial: 0, }); if (!response.nextStep) { console.log(chalk.gray("\nšŸ‘‹ Happy learning! Come back when you're ready for more.")); return null; } if (response.nextStep === "custom") { const customResponse = await prompts({ type: "text", name: "customGoal", message: "I would like to learn about:", validate: (value) => value.length > 0 ? true : "Please enter a learning goal", }); return customResponse.customGoal || null; } return response.nextStep; } export async function reviewCommand() { try { // Find all source files in the src directory const sourceFiles = getAllSourceFiles(); if (sourceFiles == null || Object.keys(sourceFiles).length === 0) { printError("āŒ No source files found. Please make sure you have files in the src/ directory"); return; } // Extract goal from file content const learningInformation = getLearningInformation(); console.log("\n"); printHeader("Code Review"); // Display which files will be reviewed console.log(chalk.cyan("šŸ“ Files to be reviewed:")); Object.keys(sourceFiles).forEach(filename => { console.log(chalk.green(` āœ“ ${filename}`)); }); // TODO: dynamic technology const data = await reviewCode({ topic: learningInformation.topic, sourceFiles: sourceFiles, skillLevel: learningInformation.skillLevel, technology: learningInformation.selectedTech, }); // Display feedback in terminal displayFeedback(data.feedback); // Save feedback to template folder const feedbackPath = saveFeedbackToTemplate(data.feedback, 1, learningInformation.selectedTech); // Generate HTML page const htmlPath = generateFeedbackHTML(data.feedback, 1); // Also save to .hackages for backup saveFeedbackToMarkdown(data.feedback, learningInformation.selectedTech, learningInformation.id); console.log("\n"); printSuccess("šŸŽ‰ Code review completed!"); if (feedbackPath) { console.log(chalk.blue(`šŸ“ Feedback saved to: ${feedbackPath}`)); } if (htmlPath) { console.log(chalk.blue(`🌐 HTML page generated: ${htmlPath}`)); console.log(chalk.gray("šŸ’” Opening feedback page in browser...")); // Open HTML page in browser openFeedbackHTML(htmlPath); } // Extract learning suggestions and prompt for next step const nextLearningGoal = await promptNextLearningStep(data.nextLearningSteps); if (nextLearningGoal) { console.log("\n" + chalk.yellow("šŸ”„ Generating your next exercise...")); // Create new learning goal for the next exercise const nextGoal = { ...learningInformation, id: learningInformation.id + "-next", topic: nextLearningGoal, }; // Generate next exercise await createNextExercise(nextGoal, 2); // exercise-2 console.log("\n" + chalk.bold.green("šŸŽ‰ Your next exercise is ready!")); console.log(chalk.cyan("=".repeat(50))); console.log(chalk.bold("šŸ“ Next exercise created:")); console.log(chalk.green(` āœ“ tests/exercise-2.spec.ts`), chalk.dim("(Your test cases)")); console.log(chalk.green(` āœ“ src/exercise-2.ts`), chalk.dim("(Your implementation file)")); console.log(chalk.green(` āœ“ instructions/exercise-2.mdx`), chalk.dim("(Exercise instructions)")); console.log("\n" + chalk.bold.yellow("šŸš€ Next steps:")); console.log(chalk.white("1. Read the instructions and test file to understand what to implement")); console.log(chalk.white("2. Open src/exercise-2.ts and start coding")); console.log(chalk.white("3. Run 'npx hackages test' to validate your implementation")); console.log(chalk.white("4. Run 'npx hackages review' to get AI feedback on your code")); } else { console.log(chalk.gray("\nšŸ‘‹ Happy learning! Come back when you're ready for more.")); } } catch (error) { printError(`āŒ Error during code review: ${error}`); } }