leetkick
Version:
A CLI tool for scaffolding LeetCode exercises with language-specific testing setups
98 lines • 4.59 kB
JavaScript
import { Command } from 'commander';
import { fetchProblem } from '../utils/leetcode-api.js';
import { getAvailableLanguages, initializeLanguage } from '../utils/templates.js';
import { createProblemFiles } from '../utils/file-operations.js';
import { findWorkspaceRoot } from '../utils/workspace.js';
import { existsSync } from 'fs';
import { join } from 'path';
export const fetchCommand = new Command('fetch')
.description('Fetch a LeetCode problem and create exercise files')
.argument('<problem-slug>', 'LeetCode problem slug (e.g., "two-sum")')
.option('-l, --language <language>', 'Programming language')
.option('-f, --force', 'Overwrite existing exercise if it exists')
.action(async (problemSlug, options) => {
try {
const workspaceRoot = findWorkspaceRoot();
if (!workspaceRoot) {
console.log('No leetkick workspace found. Run "leetkick init" first.');
console.log('Make sure you are in a directory that contains .leetkick.json or run the command from within a leetkick workspace.');
return;
}
console.log(`Fetching problem: ${problemSlug}...`);
const problem = await fetchProblem(problemSlug);
console.log(`✓ Found: [${problem.questionFrontendId}] ${problem.title}`);
const availableLanguages = await getAvailableLanguages();
if (!options.language) {
console.log('Available languages:', availableLanguages.join(', '));
throw new Error('Please specify a language with --language <lang>');
}
if (!availableLanguages.includes(options.language)) {
console.log('Available languages:', availableLanguages.join(', '));
throw new Error(`Language '${options.language}' not supported.`);
}
// Check if language workspace exists, initialize if not
const languageDir = join(workspaceRoot, options.language);
if (!existsSync(languageDir)) {
console.log(`Initializing ${options.language} workspace...`);
// Change to workspace root to create language directory there
const originalCwd = process.cwd();
process.chdir(workspaceRoot);
try {
await initializeLanguage(options.language);
}
finally {
process.chdir(originalCwd);
}
}
// Check if exercise already exists
const paddedId = problem.questionFrontendId.padStart(4, '0');
let problemDir;
let problemName;
let existingPath;
if (options.language === 'kotlin' || options.language === 'java') {
problemName = `problem${paddedId}`;
problemDir = join(languageDir, 'src', 'main', options.language, problemName);
existingPath = problemDir;
}
else if (options.language === 'rust') {
problemName = `problem_${paddedId}`;
problemDir = join(languageDir, 'src');
existingPath = join(problemDir, `${problemName}.rs`);
}
else {
problemName = `problem_${paddedId}`;
problemDir = join(languageDir, problemName);
existingPath = problemDir;
}
if (existsSync(existingPath)) {
if (!options.force) {
console.log(`❌ Exercise already exists: ${existingPath}`);
console.log('The exercise file/directory already exists.');
console.log('Options:');
console.log(' • Use --force to overwrite existing files');
console.log(' • Choose a different language');
console.log(' • Remove the existing file/directory manually');
return; // Exit gracefully without throwing error
}
else {
console.log(`⚠️ Overwriting existing exercise: ${problemName}`);
}
}
// Create problem files (change to workspace root since createProblemFiles uses process.cwd())
const originalCwd = process.cwd();
process.chdir(workspaceRoot);
try {
await createProblemFiles(problem, options.language);
console.log(`✓ Created ${options.language} exercise for: ${problem.title}`);
console.log(`📁 Problem ID: ${problemName}`);
}
finally {
process.chdir(originalCwd);
}
}
catch (error) {
console.error('Error:', error instanceof Error ? error.message : error);
throw error;
}
});
//# sourceMappingURL=fetch.js.map