mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
#!/usr/bin/env tsx
|
|
|
|
import { execSync } from 'child_process'
|
|
import { readdirSync, readFileSync, statSync } from 'fs'
|
|
import { join } from 'path'
|
|
|
|
interface FileSizeMetric {
|
|
file: string
|
|
size: number
|
|
lines: number
|
|
category: 'component' | 'utility' | 'hook' | 'type' | 'style' | 'other'
|
|
violations: string[]
|
|
}
|
|
|
|
const MAX_FILE_SIZE = 500 // lines
|
|
const MAX_COMPONENT_SIZE = 300 // lines
|
|
const MAX_UTILITY_SIZE = 200 // lines
|
|
const WARN_FILE_SIZE = 400 // lines
|
|
|
|
function categorizeFile(filePath: string): FileSizeMetric['category'] {
|
|
if (filePath.includes('component') || filePath.endsWith('.tsx')) return 'component'
|
|
if (filePath.includes('hook')) return 'hook'
|
|
if (filePath.includes('type') || filePath.endsWith('.d.ts')) return 'type'
|
|
if (filePath.includes('style') || filePath.endsWith('.css')) return 'style'
|
|
if (filePath.includes('util') || filePath.endsWith('.ts')) return 'utility'
|
|
return 'other'
|
|
}
|
|
|
|
function analyzeFileSizes(): FileSizeMetric[] {
|
|
const results: FileSizeMetric[] = []
|
|
const srcDir = 'src'
|
|
|
|
function walkDir(dir: string) {
|
|
try {
|
|
const files = readdirSync(dir)
|
|
|
|
for (const file of files) {
|
|
const fullPath = join(dir, file)
|
|
const stat = statSync(fullPath)
|
|
|
|
if (stat.isDirectory() && !['node_modules', '.next', 'dist', 'build'].includes(file)) {
|
|
walkDir(fullPath)
|
|
} else if (['.ts', '.tsx', '.css'].includes(fullPath.slice(-3))) {
|
|
analyzeFile(fullPath, results)
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Skip inaccessible directories
|
|
}
|
|
}
|
|
|
|
walkDir(srcDir)
|
|
return results
|
|
}
|
|
|
|
function analyzeFile(filePath: string, results: FileSizeMetric[]): void {
|
|
try {
|
|
const content = readFileSync(filePath, 'utf8')
|
|
const lines = content.split('\n').length
|
|
const size = Buffer.byteLength(content, 'utf8')
|
|
const category = categorizeFile(filePath)
|
|
|
|
const violations: string[] = []
|
|
|
|
// Check size limits based on category
|
|
const maxLines = category === 'component' ? MAX_COMPONENT_SIZE :
|
|
category === 'utility' ? MAX_UTILITY_SIZE :
|
|
MAX_FILE_SIZE
|
|
|
|
if (lines > maxLines) {
|
|
violations.push(`Exceeds maximum ${category} size: ${lines} lines (max: ${maxLines})`)
|
|
} else if (lines > WARN_FILE_SIZE) {
|
|
violations.push(`Large file: ${lines} lines (warning threshold: ${WARN_FILE_SIZE})`)
|
|
}
|
|
|
|
// Check for excessively long functions
|
|
const functions = content.match(/(?:function|const|export|async)\s+\w+.*{[\s\S]*?^}/gm) || []
|
|
for (const func of functions) {
|
|
const funcLines = func.split('\n').length
|
|
if (funcLines > 50) {
|
|
violations.push(`Function exceeds 50 lines (${funcLines} lines)`)
|
|
}
|
|
}
|
|
|
|
if (violations.length > 0) {
|
|
results.push({
|
|
file: filePath,
|
|
size,
|
|
lines,
|
|
category,
|
|
violations
|
|
})
|
|
}
|
|
} catch (e) {
|
|
// Skip files that can't be analyzed
|
|
}
|
|
}
|
|
|
|
// Main execution
|
|
const results = analyzeFileSizes()
|
|
|
|
const summary = {
|
|
totalFilesAnalyzed: results.length,
|
|
violatingFiles: results.length,
|
|
totalViolations: results.reduce((sum, r) => sum + r.violations.length, 0),
|
|
byCategory: {
|
|
component: results.filter(r => r.category === 'component').length,
|
|
hook: results.filter(r => r.category === 'hook').length,
|
|
utility: results.filter(r => r.category === 'utility').length,
|
|
type: results.filter(r => r.category === 'type').length,
|
|
style: results.filter(r => r.category === 'style').length,
|
|
},
|
|
largestFiles: results.sort((a, b) => b.lines - a.lines).slice(0, 10),
|
|
details: results,
|
|
timestamp: new Date().toISOString()
|
|
}
|
|
|
|
console.log(JSON.stringify(summary, null, 2))
|