Skip to main content
Glama
portel-dev

NCP - Natural Context Provider

by portel-dev
scan-repository.js5.47 kB
#!/usr/bin/env node import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const PATTERNS = { aiGenerated: [ /\.prd\.md$/, /\.draft\.md$/, /\.ai\.md$/, /\.notes\.md$/, /\.temp\.md$/, /^2025-.*\.txt$/, // Date-prefixed AI exports ], testFiles: [ /^test-.*\.js$/, /\.test\.js$/, /\.script\.js$/ ], backups: [ /\.backup\./, /\.old$/, /~$/, /\.disabled$/ ], misplaced: [ // Files that should be in docs/ but are in root /^TESTING\.md$/, /^MCP_EXPANSION_SUMMARY\.md$/, /^mcp-expansion-strategy\.md$/ ], local: [ /\.local\./, /^\.claude\.local\.md$/, /^CLAUDE\.local\.md$/ ] }; function scanDirectory(dir, ignore = ['node_modules', 'dist', '.git', '.ncp']) { const issues = []; function scan(currentPath) { try { const files = fs.readdirSync(currentPath); for (const file of files) { const fullPath = path.join(currentPath, file); const relativePath = path.relative(process.cwd(), fullPath); if (ignore.some(i => relativePath.includes(i))) continue; if (fs.statSync(fullPath).isDirectory()) { scan(fullPath); } else { // Check against patterns for (const [category, patterns] of Object.entries(PATTERNS)) { if (patterns.some(p => p.test(file))) { // Only flag files in root for certain categories const isRoot = path.dirname(relativePath) === '.'; if (category === 'aiGenerated' || category === 'testFiles' || category === 'misplaced') { if (isRoot) { issues.push({ category, file: relativePath, action: getRecommendedAction(category, file) }); } } else { issues.push({ category, file: relativePath, action: getRecommendedAction(category, file) }); } } } // Check for misplaced files in specific directories if (relativePath.startsWith('scripts/') && file.endsWith('.md')) { issues.push({ category: 'misplaced', file: relativePath, action: 'Move to docs/ with appropriate sub-extension' }); } // Check test directory for non-test files const validTestExtensions = [ '.test.ts', '.test.js', '.test.cjs', '.test.mjs', '.spec.ts', '.spec.js', '.spec.cjs', '.spec.mjs', '.ts', '.js', '.cjs', '.mjs', '.sh', '.bash', // Shell test scripts '.json', '.yaml', '.yml' // Config files for mock data ]; const isMockDirectory = relativePath.includes('/mock-') || relativePath.includes('/mocks/'); const isValidTestFile = validTestExtensions.some(ext => file.endsWith(ext)) || isMockDirectory; if (relativePath.startsWith('test/') && !isValidTestFile) { issues.push({ category: 'misplaced', file: relativePath, action: 'Non-test file in test directory' }); } } } } catch (error) { console.warn(`Warning: Could not scan ${currentPath}: ${error.message}`); } } scan(dir); return issues; } function getRecommendedAction(category, file) { switch (category) { case 'aiGenerated': return 'Should be gitignored (use sub-extension system)'; case 'testFiles': return 'Move to test/ directory or delete if obsolete'; case 'backups': return 'Delete or move to backup location'; case 'misplaced': return 'Move to appropriate directory (docs/)'; case 'local': return 'Should be gitignored (local development only)'; default: return 'Review and categorize appropriately'; } } function generateReport(issues) { if (issues.length === 0) { console.log('✅ Repository is clean!'); return; } console.log('🔍 Repository Cleanup Issues Found:\n'); // Group issues by category const groupedIssues = issues.reduce((acc, issue) => { if (!acc[issue.category]) acc[issue.category] = []; acc[issue.category].push(issue); return acc; }, {}); Object.entries(groupedIssues).forEach(([category, categoryIssues]) => { console.log(`\n📂 ${category.toUpperCase()} (${categoryIssues.length} issues):`); categoryIssues.forEach(issue => { console.log(` ❌ ${issue.file}`); console.log(` → ${issue.action}`); }); }); console.log(`\n📊 Summary: ${issues.length} total issues found`); // Provide cleanup suggestions console.log('\n💡 Quick Fix Commands:'); console.log(' # Remove test files from root:'); console.log(' rm test-*.js'); console.log(' # Move documentation to docs:'); console.log(' mv HOW-IT-WORKS.md docs/how-it-works.md'); console.log(' mv TESTING.md docs/guides/testing.md'); } // Run scan if called directly if (import.meta.url === `file://${process.argv[1]}`) { const issues = scanDirectory('.'); generateReport(issues); // Exit with error code if issues found (for CI/CD) process.exit(issues.length > 0 ? 1 : 0); } export { scanDirectory, generateReport };

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/portel-dev/ncp'

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