Skip to main content
Glama
diagnostic.js7.77 kB
const { execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); class MonorepoDiagnostic { constructor() { this.packagesDir = path.join(__dirname, '../packages'); this.rootDir = path.join(__dirname, '..'); } async diagnose() { console.log('🔍 Running monorepo diagnostic...\n'); const checks = [ () => this.checkProjectStructure(), () => this.checkPackageFiles(), () => this.checkDependencyIntegrity(), () => this.checkBuildArtifacts(), () => this.checkScriptAvailability() ]; let allPassed = true; for (const check of checks) { try { const passed = await check(); if (!passed) allPassed = false; } catch (error) { console.error(`❌ Check failed:`, error.message); allPassed = false; } } console.log('\n' + '='.repeat(50)); if (allPassed) { console.log('✅ All diagnostic checks passed!'); } else { console.log('❌ Some diagnostic checks failed. Please review the output above.'); } console.log('='.repeat(50)); return allPassed; } checkProjectStructure() { console.log('📋 Checking project structure...'); const requiredFiles = [ 'package.json', 'pnpm-workspace.yaml', 'packages', 'scripts/build.js', 'scripts/dev.js', 'scripts/clean.js' ]; let allExists = true; for (const file of requiredFiles) { const filePath = path.join(this.rootDir, file); if (fs.existsSync(filePath)) { console.log(` ✅ ${file}`); } else { console.log(` ❌ ${file} - Missing`); allExists = false; } } return allExists; } checkPackageFiles() { console.log('\n📦 Checking package files...'); if (!fs.existsSync(this.packagesDir)) { console.log(' ❌ packages directory not found'); return false; } const packages = fs.readdirSync(this.packagesDir); let allValid = true; for (const pkg of packages) { const pkgPath = path.join(this.packagesDir, pkg); const packageJsonPath = path.join(pkgPath, 'package.json'); if (fs.existsSync(packageJsonPath)) { try { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); console.log(` ✅ ${pkg} - ${packageJson.name}`); // 检查基本字段 if (!packageJson.name) { console.log(` ⚠️ Missing name field`); allValid = false; } if (!packageJson.version) { console.log(` ⚠️ Missing version field`); } } catch (error) { console.log(` ❌ ${pkg} - Invalid package.json: ${error.message}`); allValid = false; } } else { console.log(` ❌ ${pkg} - No package.json found`); allValid = false; } } return allValid; } checkDependencyIntegrity() { console.log('\n🔗 Checking dependency integrity...'); try { const packages = this.discoverPackages(); let allValid = true; for (const pkg of packages) { const packageJson = JSON.parse(fs.readFileSync(path.join(pkg.path, 'package.json'), 'utf8')); const workspaceDeps = this.extractWorkspaceDependencies(packageJson); console.log(` 📦 ${pkg.name}:`); if (workspaceDeps.length === 0) { console.log(` ℹ️ No workspace dependencies`); } else { for (const dep of workspaceDeps) { const depExists = packages.some(p => p.name === dep); if (depExists) { console.log(` ✅ ${dep}`); } else { console.log(` ❌ ${dep} - Dependency not found in workspace`); allValid = false; } } } } return allValid; } catch (error) { console.log(` ❌ Failed to check dependencies: ${error.message}`); return false; } } checkBuildArtifacts() { console.log('\n🏗️ Checking build artifacts...'); const packages = this.discoverPackages(); let allValid = true; for (const pkg of packages) { const packageJson = JSON.parse(fs.readFileSync(path.join(pkg.path, 'package.json'), 'utf8')); console.log(` 📦 ${pkg.name}:`); // 检查主入口文件 if (packageJson.main) { const mainPath = path.join(pkg.path, packageJson.main); if (fs.existsSync(mainPath)) { console.log(` ✅ main: ${packageJson.main}`); } else { console.log(` ❌ main: ${packageJson.main} - File not found`); allValid = false; } } // 检查类型定义文件 if (packageJson.types) { const typesPath = path.join(pkg.path, packageJson.types); if (fs.existsSync(typesPath)) { console.log(` ✅ types: ${packageJson.types}`); } else { console.log(` ❌ types: ${packageJson.types} - File not found`); allValid = false; } } // 检查 dist 目录 const distPath = path.join(pkg.path, 'dist'); if (fs.existsSync(distPath)) { const distFiles = fs.readdirSync(distPath); console.log(` ✅ dist/ (${distFiles.length} files)`); } else if (packageJson.scripts && packageJson.scripts.build) { console.log(` ⚠️ dist/ directory not found (package has build script)`); } } return allValid; } checkScriptAvailability() { console.log('\n🔧 Checking script availability...'); const packages = this.discoverPackages(); let hasIssues = false; for (const pkg of packages) { const packageJson = JSON.parse(fs.readFileSync(path.join(pkg.path, 'package.json'), 'utf8')); console.log(` 📦 ${pkg.name}:`); const scripts = packageJson.scripts || {}; const commonScripts = ['build', 'test', 'lint', 'clean']; for (const script of commonScripts) { if (scripts[script]) { console.log(` ✅ ${script}: ${scripts[script]}`); } else { console.log(` ℹ️ ${script}: not available`); } } // 检查 watch 相关脚本 const watchScripts = ['build:watch', 'dev', 'watch']; const hasWatchScript = watchScripts.some(script => scripts[script]); if (hasWatchScript) { const watchScript = watchScripts.find(script => scripts[script]); console.log(` ✅ watch: ${watchScript} - ${scripts[watchScript]}`); } else { console.log(` ⚠️ watch: no watch scripts available`); } } return !hasIssues; } discoverPackages() { return fs.readdirSync(this.packagesDir) .filter(dir => { const packagePath = path.join(this.packagesDir, dir, 'package.json'); return fs.existsSync(packagePath); }) .map(dir => { const packagePath = path.join(this.packagesDir, dir, 'package.json'); const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); return { name: packageJson.name, path: path.join(this.packagesDir, dir) }; }); } extractWorkspaceDependencies(packageJson) { const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; return Object.keys(deps).filter(dep => deps[dep].startsWith('workspace:')); } } // 执行诊断 if (require.main === module) { new MonorepoDiagnostic().diagnose().catch(error => { console.error('💥 Diagnostic failed:', error); process.exit(1); }); } module.exports = MonorepoDiagnostic;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zaizaizhao/mcp-swagger-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server