UNPKG

@jmkim85/dev-flow-mcp

Version:

MCP-based Dev Flow - AI-powered development workflow management with 13 essential tools for TDD and context management

132 lines 6.11 kB
// project-utils.ts - Project root detection and file utilities import { promises as fs } from 'fs'; import { join } from 'path'; // Smart project root detection export async function detectProjectRoot() { console.error('🔍 Starting project root detection...'); // 1. Check environment variable (highest priority) if (process.env.DEV_FLOW_PROJECT_ROOT) { console.error(`✅ Using DEV_FLOW_PROJECT_ROOT: ${process.env.DEV_FLOW_PROJECT_ROOT}`); return process.env.DEV_FLOW_PROJECT_ROOT; } // 2. Check VSCode workspace environment variables (most reliable) if (process.env.VSCODE_WORKSPACE_FOLDER) { console.error(`✅ Using VSCODE_WORKSPACE_FOLDER: ${process.env.VSCODE_WORKSPACE_FOLDER}`); return process.env.VSCODE_WORKSPACE_FOLDER; } // 3. Try current working directory first (often more specific than VSCODE_CWD) const cwd = process.cwd(); console.error(`🔍 Checking current working directory: ${cwd}`); const projectRootFromCwd = await findProjectRoot(cwd); if (projectRootFromCwd) { console.error(`✅ Found project root from cwd: ${projectRootFromCwd}`); // If we have VSCODE_CWD, compare which one is more specific if (process.env.VSCODE_CWD) { const vscodeCwd = process.env.VSCODE_CWD; console.error(`🔍 Comparing with VSCODE_CWD: ${vscodeCwd}`); // If current directory is a subdirectory of VSCODE_CWD, prefer current directory if (cwd.startsWith(vscodeCwd) && cwd !== vscodeCwd) { console.error(`✅ Current directory is more specific than VSCODE_CWD, using: ${projectRootFromCwd}`); return projectRootFromCwd; } // If VSCODE_CWD is a subdirectory of current directory, check if it has project markers if (vscodeCwd.startsWith(cwd)) { const projectRootFromVscode = await findProjectRoot(vscodeCwd); if (projectRootFromVscode) { console.error(`✅ Found project root from VSCODE_CWD: ${projectRootFromVscode}`); return projectRootFromVscode; } } } return projectRootFromCwd; } // 4. Fall back to VSCODE_CWD if current directory doesn't have project markers if (process.env.VSCODE_CWD) { console.error(`🔍 Checking VSCODE_CWD: ${process.env.VSCODE_CWD}`); const projectRootFromVscode = await findProjectRoot(process.env.VSCODE_CWD); if (projectRootFromVscode) { console.error(`✅ Found project root from VSCODE_CWD: ${projectRootFromVscode}`); return projectRootFromVscode; } else { console.error(`⚠️ No project markers found in VSCODE_CWD, using as-is: ${process.env.VSCODE_CWD}`); return process.env.VSCODE_CWD; } } // 5. SSH environment: Check for VSCode Remote SSH specific variables if (process.env.SSH_CLIENT || process.env.SSH_CONNECTION) { console.error('🔗 SSH environment detected, checking VSCode Remote variables...'); // VSCode Remote SSH often sets these if (process.env.VSCODE_IPC_HOOK_CLI) { console.error('📡 VSCode Remote SSH detected'); } // In SSH, VSCode might set the workspace in different variables const remoteWorkspace = process.env.VSCODE_WORKSPACE || process.env.REMOTE_CONTAINERS_IPC; if (remoteWorkspace) { console.error(`✅ Using remote workspace: ${remoteWorkspace}`); return remoteWorkspace; } } // 6. Last resort: use current working directory console.error(`⚠️ No project root found, using current directory: ${cwd}`); return cwd; } // Find project root by looking for common project markers export async function findProjectRoot(startPath) { const projectMarkers = [ '.devflow', // Existing Dev Flow project (highest priority) '.git', // Git repository 'package.json', // Node.js 'requirements.txt', // Python 'pyproject.toml', // Modern Python 'Cargo.toml', // Rust 'go.mod', // Go 'pom.xml', // Java Maven 'build.gradle', // Java Gradle 'composer.json', // PHP 'Gemfile', // Ruby 'mix.exs', // Elixir 'deno.json', // Deno 'tsconfig.json', // TypeScript '.vscode', // VSCode workspace '.idea' // IntelliJ workspace ]; let currentPath = startPath; let searchDepth = 0; const maxDepth = 10; // Prevent infinite loops console.error(`🔍 Searching for project markers in: ${currentPath}`); while (currentPath !== '/' && currentPath !== '' && !currentPath.match(/^[A-Z]:\\?$/) && searchDepth < maxDepth) { console.error(`📁 Checking directory: ${currentPath}`); for (const marker of projectMarkers) { try { const markerPath = join(currentPath, marker); await fs.access(markerPath); console.error(`✅ Found project marker '${marker}' at: ${currentPath}`); return currentPath; // Found a project marker } catch { // Continue searching } } const parentPath = join(currentPath, '..'); if (parentPath === currentPath) break; // Reached root currentPath = parentPath; searchDepth++; } console.error(`❌ No project markers found after searching ${searchDepth} directories`); return null; // No project root found } // Get package version dynamically (deprecated - use version-manager.ts) export async function getPackageVersion() { try { // Import the centralized version manager const { getVersion } = await import('./version-manager.js'); return await getVersion(); } catch (error) { console.error('Warning: Could not read package version:', error); return '0.0.0-error'; // Fallback version indicating error } } //# sourceMappingURL=project-utils.js.map