cyclic-dependency-fixer
Version:
AI-powered tool to detect and fix circular dependencies in JavaScript/TypeScript projects. Features intelligent refactoring with Claude/GPT-4, codebase pattern learning, and context-aware fix recommendations
151 lines (143 loc) • 5.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AIRefactoringGenerator = void 0;
const types_1 = require("../../domain/models/types");
class AIRefactoringGenerator {
constructor(aiProvider, fileSystem) {
this.aiProvider = aiProvider;
this.fileSystem = fileSystem;
}
async generateRefactoring(cycle, modules, strategy) {
if (!this.aiProvider.isAvailable()) {
return null;
}
const cycleCode = await this.extractFullCycleCode(cycle, modules);
const prompt = this.buildRefactoringPrompt(cycle, cycleCode, strategy);
const response = await this.aiProvider.generateCode({
prompt,
maxTokens: 4096,
temperature: 0.2,
systemPrompt: `You are an expert TypeScript refactoring assistant.
Generate complete, production-ready refactoring code that:
1. Fixes the circular dependency using the specified strategy
2. Maintains type safety
3. Follows SOLID principles
4. Preserves existing functionality
5. Uses clear, descriptive naming
Respond in JSON format:
{
"strategy": "strategy name",
"codeSnippets": [
{
"filePath": "path/to/file.ts",
"code": "complete code content",
"description": "what this does",
"isNewFile": boolean
}
],
"instructions": ["step 1", "step 2", ...],
"explanation": "detailed explanation",
"impact": "low|medium|high"
}`,
});
return this.parseRefactoringSuggestion(response.content);
}
async generateManualSteps(cycle, modules, strategy) {
const suggestion = await this.generateRefactoring(cycle, modules, strategy);
if (!suggestion) {
return [];
}
return suggestion.codeSnippets.map((snippet) => ({
description: snippet.description,
file: snippet.filePath,
code: snippet.code,
}));
}
async explainCycle(cycle, modules) {
if (!this.aiProvider.isAvailable()) {
return 'AI analysis not available. Configure an AI provider to get detailed explanations.';
}
const cycleCode = await this.extractFullCycleCode(cycle, modules);
const prompt = `Analyze this circular dependency and explain:
1. Why it exists (root cause)
2. What problems it might cause
3. How to prevent similar issues in the future
**Circular Dependency:**
${this.describeCycle(cycle)}
**Code:**
${cycleCode}
Provide a clear, concise explanation for developers.`;
const response = await this.aiProvider.analyze({
prompt,
maxTokens: 1024,
temperature: 0.4,
});
return response.content;
}
async extractFullCycleCode(cycle, modules) {
const codeSnippets = [];
const uniquePaths = cycle.paths.slice(0, -1);
for (const path of uniquePaths) {
const module = modules.get(path);
if (!module)
continue;
try {
const content = await this.fileSystem.readFile(path);
codeSnippets.push(`// File: ${path}\n${content}`);
}
catch {
continue;
}
}
return codeSnippets.join('\n\n// ============================================\n\n');
}
buildRefactoringPrompt(cycle, cycleCode, strategy) {
const strategyDescription = this.getStrategyDescription(strategy);
return `Generate complete refactoring code to fix this circular dependency using the ${strategy} strategy.
**Strategy:** ${strategy}
${strategyDescription}
**Circular Dependency:**
${this.describeCycle(cycle)}
**Current Code:**
${cycleCode}
Generate COMPLETE, WORKING code for all files that need to be created or modified.
Include proper TypeScript types and imports.`;
}
getStrategyDescription(strategy) {
const descriptions = {
[types_1.FixStrategy.EXTRACT_SHARED]: 'Extract common code into a new shared module that both files can import without creating a cycle.',
[types_1.FixStrategy.DYNAMIC_IMPORT]: 'Convert static imports to dynamic imports to break the cycle at runtime.',
[types_1.FixStrategy.DEPENDENCY_INJECTION]: 'Use dependency injection pattern to inject dependencies rather than importing them directly.',
[types_1.FixStrategy.MOVE_CODE]: 'Move code between files to eliminate the circular reference while maintaining functionality.',
[types_1.FixStrategy.BARREL_FILE]: 'Create a barrel file (index.ts) to centralize exports and break the cycle.',
};
return descriptions[strategy] || 'Fix the circular dependency.';
}
describeCycle(cycle) {
const lines = [];
lines.push(`Files involved: ${cycle.paths.length - 1}`);
cycle.paths.forEach((path, i) => {
if (i < cycle.paths.length - 1) {
lines.push(` ${i + 1}. ${path}`);
}
});
lines.push('\nImport chain:');
cycle.edges.forEach((edge) => {
lines.push(` ${edge.from} -> ${edge.to} (line ${edge.importInfo.line}, imports: ${edge.importInfo.identifiers.join(', ')})`);
});
return lines.join('\n');
}
parseRefactoringSuggestion(content) {
try {
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (jsonMatch) {
return JSON.parse(jsonMatch[0]);
}
}
catch {
}
return null;
}
}
exports.AIRefactoringGenerator = AIRefactoringGenerator;
//# sourceMappingURL=AIRefactoringGenerator.js.map