UNPKG

@paulohenriquevn/m2js

Version:

Transform TypeScript/JavaScript code into LLM-friendly Markdown summaries + Smart Dead Code Detection + Graph-Deep Diff Analysis. Extract exported functions, classes, and JSDoc comments for better AI context with 60%+ token reduction. Intelligent dead cod

364 lines 12.3 kB
"use strict"; /** * Git Integration for Graph-Deep Diff Analysis * Handles git operations for baseline comparisons */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.GitIntegrator = void 0; const child_process_1 = require("child_process"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const os_1 = require("os"); /** * Git integration class for handling repository operations */ class GitIntegrator { constructor(repoPath) { this.repoPath = repoPath; this.validateGitRepo(); } /** * Validate that the path is a git repository */ validateGitRepo() { try { (0, child_process_1.execSync)('git rev-parse --git-dir', { cwd: this.repoPath, stdio: 'pipe', }); } catch { throw new Error(`Not a git repository: ${this.repoPath}`); } } /** * Get the current git reference (branch or commit) */ getCurrentRef() { try { const result = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result.trim(); } catch { // Fallback to commit hash try { const result = (0, child_process_1.execSync)('git rev-parse HEAD', { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result.trim().substring(0, 8); } catch { return 'unknown'; } } } /** * Check if a git reference exists */ refExists(ref) { try { (0, child_process_1.execSync)(`git rev-parse --verify ${ref}`, { cwd: this.repoPath, stdio: 'pipe', }); return true; } catch { return false; } } /** * Get list of files at a specific git reference */ getFilesAtRef(ref, patterns) { try { // Get list of files at the reference let cmd = `git ls-tree -r --name-only ${ref}`; const result = (0, child_process_1.execSync)(cmd, { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); let files = result .trim() .split('\n') .filter(f => f.length > 0); // Filter by TypeScript/JavaScript files files = files.filter(file => /\.(ts|tsx|js|jsx)$/.test(file) && !file.includes('node_modules') && !file.includes('.d.ts')); // Apply additional patterns if provided if (patterns && patterns.length > 0) { const includePatterns = patterns.filter(p => !p.startsWith('!')); const excludePatterns = patterns .filter(p => p.startsWith('!')) .map(p => p.slice(1)); if (includePatterns.length > 0) { files = files.filter(file => includePatterns.some(pattern => this.matchPattern(file, pattern))); } if (excludePatterns.length > 0) { files = files.filter(file => !excludePatterns.some(pattern => this.matchPattern(file, pattern))); } } return files.map(file => path.join(this.repoPath, file)); } catch (error) { throw new Error(`Failed to get files at ref ${ref}: ${error.message}`); } } /** * Get file content at a specific git reference */ getFileContentAtRef(filePath, ref) { try { const relativePath = path.relative(this.repoPath, filePath); const result = (0, child_process_1.execSync)(`git show ${ref}:${relativePath}`, { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result; } catch { // File might not exist at this ref return ''; } } /** * Create temporary directory with files from a git reference */ async createTempWorkspace(ref, patterns) { const tempDir = path.join((0, os_1.tmpdir)(), `m2js-workspace-${ref}-${Date.now()}`); try { // Create temp directory fs.mkdirSync(tempDir, { recursive: true }); // Get files at the reference const files = this.getFilesAtRef(ref, patterns); // Copy files to temp directory maintaining structure for (const filePath of files) { const relativePath = path.relative(this.repoPath, filePath); const tempFilePath = path.join(tempDir, relativePath); const tempFileDir = path.dirname(tempFilePath); // Create directory structure fs.mkdirSync(tempFileDir, { recursive: true }); // Get file content at ref and write to temp location const content = this.getFileContentAtRef(filePath, ref); if (content) { fs.writeFileSync(tempFilePath, content, 'utf8'); } } return tempDir; } catch (error) { // Cleanup on error if (fs.existsSync(tempDir)) { fs.rmSync(tempDir, { recursive: true, force: true }); } throw new Error(`Failed to create workspace for ${ref}: ${error.message}`); } } /** * Get changes between two references */ getChangesBetween(baseRef, currentRef = 'HEAD') { try { const cmd = `git diff --name-status --numstat ${baseRef}...${currentRef}`; const result = (0, child_process_1.execSync)(cmd, { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); if (!result.trim()) { return []; } const changes = []; const lines = result.trim().split('\n'); for (const line of lines) { const parts = line.split('\t'); if (parts.length >= 3) { const [linesAdded, linesDeleted, filePath] = parts; // Skip non-JS/TS files if (!/\.(ts|tsx|js|jsx)$/.test(filePath)) { continue; } let changeType = 'modified'; if (linesAdded === '-' && linesDeleted === '-') { changeType = 'renamed'; } else if (linesDeleted === '0') { changeType = 'added'; } else if (linesAdded === '0') { changeType = 'deleted'; } changes.push({ path: filePath, changeType, linesAdded: linesAdded === '-' ? 0 : parseInt(linesAdded, 10), linesDeleted: linesDeleted === '-' ? 0 : parseInt(linesDeleted, 10), }); } } return changes; } catch (error) { throw new Error(`Failed to get changes between ${baseRef} and ${currentRef}: ${error.message}`); } } /** * Get list of recent commits */ getRecentCommits(count = 10) { try { const result = (0, child_process_1.execSync)(`git log --oneline -${count} --pretty=format:"%H|%s|%ai"`, { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result .trim() .split('\n') .map(line => { const [hash, message, date] = line.split('|'); return { hash: hash.substring(0, 8), message, date }; }); } catch { return []; } } /** * Resolve reference to actual commit hash */ resolveRef(ref) { try { // Handle special references if (ref === 'previous') { return this.getPreviousCommit(); } const result = (0, child_process_1.execSync)(`git rev-parse ${ref}`, { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result.trim(); } catch { throw new Error(`Invalid git reference: ${ref}`); } } /** * Get the previous commit hash */ getPreviousCommit() { try { const result = (0, child_process_1.execSync)('git rev-parse HEAD~1', { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result.trim(); } catch { throw new Error('No previous commit found'); } } /** * Simple pattern matching for file paths */ matchPattern(filePath, pattern) { // Convert glob pattern to regex const regexPattern = pattern .replace(/\*\*/g, '.*') .replace(/\*/g, '[^/]*') .replace(/\?/g, '[^/]'); const regex = new RegExp(`^${regexPattern}$`); return regex.test(filePath); } /** * Cleanup temporary workspace */ cleanupWorkspace(workspacePath) { try { if (fs.existsSync(workspacePath)) { fs.rmSync(workspacePath, { recursive: true, force: true }); } } catch { // Ignore cleanup errors } } /** * Check if working directory is clean */ isWorkingDirectoryClean() { try { const result = (0, child_process_1.execSync)('git status --porcelain', { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result.trim() === ''; } catch { return false; } } /** * Get current branch name */ getCurrentBranch() { try { const result = (0, child_process_1.execSync)('git branch --show-current', { cwd: this.repoPath, encoding: 'utf8', stdio: 'pipe', }); return result.trim(); } catch { return 'unknown'; } } } exports.GitIntegrator = GitIntegrator; //# sourceMappingURL=git-integrator.js.map