UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

228 lines 9.37 kB
/** * Project Environment Detector * Detects project type, languages, frameworks, build systems, and package managers */ import fs from 'fs-extra'; import * as path from 'path'; import { glob } from 'glob'; import * as os from 'os'; import { LanguageConfigManager } from './LanguageConfigManager.js'; export class ProjectEnvironmentDetector { projectRoot; languageManager; environment; constructor(projectRoot) { this.projectRoot = projectRoot; this.languageManager = new LanguageConfigManager(); this.environment = { languages: [], frameworks: [], buildSystems: [], packageManagers: [], operatingSystem: os.platform(), architecture: os.arch(), projectType: 'single' }; } async detectEnvironment() { await this.detectLanguages(); await this.detectFrameworks(); await this.detectBuildSystems(); this.determineProjectType(); return this.environment; } async detectLanguages() { // Detect languages by file extensions const allFiles = await glob('**/*', { cwd: this.projectRoot, ignore: ['node_modules/**', 'dist/**', 'build/**', '.git/**'], absolute: false }); const languageStats = new Map(); let totalLinesOfCode = 0; // Count files by language for (const file of allFiles) { const ext = path.extname(file).toLowerCase().substring(1); const language = this.languageManager.getLanguageFromExtension(ext); if (language) { const stats = languageStats.get(language) || { files: 0, linesOfCode: 0 }; stats.files++; // Count lines of code try { const content = await fs.readFile(path.join(this.projectRoot, file), 'utf-8'); const loc = content.split('\n').length; stats.linesOfCode += loc; totalLinesOfCode += loc; } catch (error) { // Skip files that can't be read } languageStats.set(language, stats); } } // Convert to language info this.environment.languages = Array.from(languageStats.entries()).map(([language, stats]) => { const config = this.languageManager.getConfig(language); return { name: config.name, percentage: totalLinesOfCode > 0 ? (stats.linesOfCode / totalLinesOfCode) * 100 : 0, files: stats.files, linesOfCode: stats.linesOfCode, entryPoints: [], buildFiles: [], packageFiles: [] }; }).sort((a, b) => b.percentage - a.percentage); } async detectFrameworks() { const frameworks = new Set(); for (const language of this.languageManager.getAllLanguages()) { const config = this.languageManager.getConfig(language); if (!config) continue; // Check package files for framework dependencies for (const packageFile of config.packageFiles) { const packageFiles = await glob(packageFile, { cwd: this.projectRoot, ignore: ['node_modules/**'], absolute: false }); for (const file of packageFiles) { try { const content = await fs.readFile(path.join(this.projectRoot, file), 'utf-8'); // Check for framework detection patterns for (const [framework, patterns] of Object.entries(config.frameworkDetection)) { for (const pattern of patterns) { if (content.includes(pattern)) { frameworks.add(framework); } } } } catch (error) { // Skip files that can't be read } } } } this.environment.frameworks = Array.from(frameworks); } async detectBuildSystems() { const buildSystems = new Set(); const packageManagers = new Set(); // Build system detection const buildFiles = [ { pattern: 'webpack.config.*', system: 'Webpack' }, { pattern: 'vite.config.*', system: 'Vite' }, { pattern: 'rollup.config.*', system: 'Rollup' }, { pattern: 'gulpfile.*', system: 'Gulp' }, { pattern: 'Gruntfile.*', system: 'Grunt' }, { pattern: 'CMakeLists.txt', system: 'CMake' }, { pattern: 'Makefile', system: 'Make' }, { pattern: 'build.gradle', system: 'Gradle' }, { pattern: 'pom.xml', system: 'Maven' }, { pattern: 'Cargo.toml', system: 'Cargo' }, { pattern: 'go.mod', system: 'Go Modules' }, { pattern: 'meson.build', system: 'Meson' }, { pattern: 'BUILD', system: 'Bazel' } ]; for (const { pattern, system } of buildFiles) { const files = await glob(pattern, { cwd: this.projectRoot, ignore: ['node_modules/**'], absolute: false }); if (files.length > 0) { buildSystems.add(system); } } // Package manager detection const packageFiles = [ { pattern: 'package.json', manager: 'npm' }, { pattern: 'yarn.lock', manager: 'Yarn' }, { pattern: 'pnpm-lock.yaml', manager: 'pnpm' }, { pattern: 'composer.json', manager: 'Composer' }, { pattern: 'Pipfile', manager: 'Pipenv' }, { pattern: 'poetry.lock', manager: 'Poetry' }, { pattern: 'requirements.txt', manager: 'pip' }, { pattern: 'Gemfile', manager: 'Bundler' }, { pattern: 'Cargo.toml', manager: 'Cargo' }, { pattern: 'go.mod', manager: 'Go Modules' }, { pattern: 'pubspec.yaml', manager: 'Pub' } ]; for (const { pattern, manager } of packageFiles) { const files = await glob(pattern, { cwd: this.projectRoot, ignore: ['node_modules/**'], absolute: false }); if (files.length > 0) { packageManagers.add(manager); } } this.environment.buildSystems = Array.from(buildSystems); this.environment.packageManagers = Array.from(packageManagers); } determineProjectType() { // Check for monorepo indicators const monorepoIndicators = ['lerna.json', 'rush.json', 'pnpm-workspace.yaml', 'workspace']; for (const indicator of monorepoIndicators) { try { if (fs.existsSync(path.join(this.projectRoot, indicator))) { this.environment.projectType = 'monorepo'; return; } } catch (error) { // Continue checking } } // Check for mobile app indicators const mobileIndicators = ['android/', 'ios/', 'flutter/', 'pubspec.yaml', '*.xcodeproj']; for (const indicator of mobileIndicators) { try { const files = glob.sync(indicator, { cwd: this.projectRoot }); if (files.length > 0) { this.environment.projectType = 'mobile'; return; } } catch (error) { // Continue checking } } // Check for desktop app indicators if (this.environment.frameworks.some(f => ['Electron', 'WPF', 'WinForms', 'Qt', 'GTK'].includes(f))) { this.environment.projectType = 'desktop'; return; } // Check for web app indicators if (this.environment.frameworks.some(f => ['React', 'Vue', 'Angular', 'Svelte'].includes(f))) { this.environment.projectType = 'web'; return; } // Check for API indicators if (this.environment.frameworks.some(f => ['Express', 'FastAPI', 'Django', 'Spring', 'ASP.NET Core'].includes(f))) { this.environment.projectType = 'api'; return; } // Check for library indicators if (fs.existsSync(path.join(this.projectRoot, 'lib')) || fs.existsSync(path.join(this.projectRoot, 'src/lib'))) { this.environment.projectType = 'library'; return; } // Check for microservice indicators if (fs.existsSync(path.join(this.projectRoot, 'Dockerfile')) || fs.existsSync(path.join(this.projectRoot, 'docker-compose.yml'))) { this.environment.projectType = 'microservice'; return; } // Default to single project this.environment.projectType = 'single'; } getEnvironment() { return this.environment; } } //# sourceMappingURL=ProjectEnvironmentDetector.js.map