hackages
Version:
CLI tool for learning software development concepts through test-driven development
107 lines (106 loc) • 3.56 kB
JavaScript
import { Command } from "commander";
import dotenv from "dotenv";
import { generateCommand } from "./commands/generate.js";
import { testCommand } from "./commands/test.js";
import { reviewCommand } from "./commands/review.js";
import { interactiveCommand } from "./commands/interactive.js";
import { loginCommand, logoutCommand } from "./commands/login.js";
import { onboardingCommand } from "./commands/onboarding.js";
import { loadCommand } from "./commands/load.js";
import { hintCommand } from "./commands/hint.js";
import { checkIfLearningJSONIsEmpty, getCurrentUser } from "./services/auth.js";
// Load environment variables
dotenv.config();
const program = new Command();
const currentUser = getCurrentUser();
const userStatus = currentUser
? `\nLogged in as: ${currentUser.name || currentUser.login}`
: "";
program
.name("hackages")
.description("🎯 Learn software development concepts through test-driven development\n" +
"Run 'hackages' to start your learning journey!" +
userStatus)
.version("0.4.0")
.option("-l, --load <exercise-id>", "Load an exercise from the Hackages API");
// Test command - runs the tests for current exercise
program
.command("test")
.description("Run tests for the current exercise")
.action(async () => {
await testCommand();
});
// Review command - gets feedback on implementation
program
.command("review")
.description("Get AI-powered code review and feedback")
.action(async () => {
await reviewCommand();
});
// Continue command - interactive mode for existing exercises
program
.command("continue")
.description("Continue working on existing exercise (interactive mode)")
.action(async () => {
await interactiveCommand();
});
// Login command - authenticate with GitHub
program
.command("login")
.description("Login with your GitHub account")
.action(async () => {
await loginCommand();
});
// Logout command - clear authentication
program
.command("logout")
.description("Logout from your account")
.action(async () => {
await logoutCommand();
});
// Load command - load an exercise from the API
program
.command("load")
.description("Load an exercise from the Hackages API")
.argument("<exercise-id>", "The exercise ID to load")
.action(async (exerciseId) => {
await loadCommand(exerciseId);
});
// Hint command - watch for code changes and get real-time hints
program
.command("hint")
.description("Watch your code and get real-time AI-powered hints")
.action(async () => {
await hintCommand();
});
// Handle -l or --load flag before any command runs
program.hook('preAction', async (thisCommand, actionCommand) => {
const opts = thisCommand.opts();
if (opts.load) {
await loadCommand(opts.load);
process.exit(0);
}
});
// Default behavior - start learning journey
program.action(async () => {
// check if there is a learning.json file in the .hackages directory at HOME directory
if (checkIfLearningJSONIsEmpty()) {
await onboardingCommand();
}
else {
// Existing user - use full flow with authentication
const learningGoals = await generateCommand();
if (!learningGoals) {
return; // Exit if no learning goals were collected
}
await generateCommand(learningGoals);
}
});
// Handle legacy --continue flag for backward compatibility
if (process.argv.includes("--continue")) {
interactiveCommand();
}
else {
program.parse();
}